void
SoUnknownEngine::copyContents(const SoFieldContainer *fromFC,
			      SbBool copyConnections)
//
////////////////////////////////////////////////////////////////////////
{
    // Make sure the copy has the correct class name
    const SoUnknownEngine *fromUnk = (const SoUnknownEngine *) fromFC;
    setClassName(fromUnk->className);

    // For each input in the original engine, create a new input and add
    // it to the new engine

    // NOTE: We can't use SoEngine::copyContents() to copy the field
    // data, since that uses SoFieldData::overlay(), which assumes the
    // fields have the same offsets in both engines. Instead, we just
    // copy the field values ourselves.

    const SoFieldData *fromData = fromUnk->getFieldData();
    SoFieldData  *toData	= (SoFieldData *) getFieldData();
    int i;
    for (i = 0; i < fromData->getNumFields(); i++) {

	SoField      *fromField	= fromData->getField(fromUnk, i);
        const SbName fieldName	= fromData->getFieldName(i);
        SoType       fieldType	= fromField->getTypeId();
        SoField      *toField	= (SoField *) (fieldType.createInstance());

        toField->enableNotify(FALSE);
        toField->setContainer(this);
        toField->setDefault(TRUE);
        toField->enableNotify(TRUE);

        toData->addField(this, fieldName.getString(), toField);

	toField->setContainer(this);
	toField->copyFrom(*fromField);
	toField->setIgnored(fromField->isIgnored());
	toField->setDefault(fromField->isDefault());
	toField->fixCopy(copyConnections);
	if (fromField->isConnected() && copyConnections)
	    toField->copyConnection(fromField);
    }

    // Copy the outputs
    SoEngineOutputData *toOutData = (SoEngineOutputData *) getOutputData();

    SoEngineOutputList outList;
    fromUnk->getOutputs(outList);

    for(i = 0; i < outList.getLength(); i++) {
        SoEngineOutput *newOut = new SoEngineOutput;
        const SoType outType = outList[i]->getConnectionType();
	SbName outName;
        getOutputName( outList[i], outName );
	toOutData->addOutput(this, outName.getString(), newOut, outType);
	newOut->setContainer(this);
    }
}
void
SoUnknownNode::createFromIsA(SoMFString *isA)
//
////////////////////////////////////////////////////////////////////////
{
    for (int i = 0; i < isA->getNum(); i++) {
	SoType t = SoType::fromName((*isA)[i]);

	if (t.canCreateInstance() &&
	    t.isDerivedFrom(SoNode::getClassTypeId())) {

	    SoNode *alternateRep = (SoNode *)t.createInstance();
	    alternateRep->ref();
#ifdef DEBUG
	    if (alternateRep == NULL) {
		SoDebugError::post("SoUnknownNode::createFromIsA",
				   "SoType.createInstance returned "
				   "NULL (type %s)",
				   t.getName().getString());
		return;
	    }
#endif
	    // Copy over all fields that are shared:
	    int num = instanceFieldData->getNumFields();
	    for (int j=0; j<num; j++) {
		const SbName &fieldName = instanceFieldData->getFieldName(j);
		SoField *f = instanceFieldData->getField(this, j);
		// Don't copy over fields with default values:
		if (f->isDefault()) continue;
		
		SoField *nf = alternateRep->getField(fieldName);
		if (nf != NULL && nf->getTypeId() == f->getTypeId()) {
		    nf->copyFrom(*f);
		    if (f->isConnectedFromField()) {
			SoField *cf;
			f->getConnectedField(cf);
			nf->connectFrom(cf);
		    } else if (f->isConnectedFromEngine()) {
			SoEngineOutput *eo;
			f->getConnectedEngine(eo);
			nf->connectFrom(eo);
		    }
		}
	    }
	    // And if alternateRep is a group, copy over hidden
	    // children:
	    if (alternateRep->isOfType(SoGroup::getClassTypeId())) {
		SoGroup *g = (SoGroup *)alternateRep;
		for (int kid = 0; kid < hiddenChildren.getLength();
		     kid++) {
		    g->addChild(hiddenChildren[kid]);
		}
	    }
	    addChild(alternateRep);
	    return;
	}
    }
}
void
SoUnknownNode::copyContents(const SoFieldContainer *fromFC,
			    SbBool copyConnections)
//
////////////////////////////////////////////////////////////////////////
{
    // Make sure the copy has the correct class name
    const SoUnknownNode *fromUnk = (const SoUnknownNode *) fromFC;
    setClassName(fromUnk->className);

    // For each field in the original node, create a new field and add
    // it to the new node

    // NOTE: We can't use SoNode::copyContents() to copy the field
    // data, since that uses SoFieldData::overlay(), which assumes the
    // fields have the same offsets in both nodes. Instead, we just
    // copy the field values ourselves.

    const SoFieldData *fromData = fromUnk->getFieldData();
    SoFieldData  *toData	= (SoFieldData *) getFieldData();

    int i;
    for (i = 0; i < fromData->getNumFields(); i++) {

	SoField      *fromField	= fromData->getField(fromUnk, i);
        const SbName fieldName	= fromData->getFieldName(i);
        SoType       fieldType	= fromField->getTypeId();
        SoField      *toField	= (SoField *) (fieldType.createInstance());

        toField->enableNotify(FALSE);
        toField->setContainer(this);
        toField->setDefault(TRUE);
        toField->enableNotify(TRUE);

        toData->addField(this, fieldName.getString(), toField);

	toField->setContainer(this);
	toField->copyFrom(*fromField);
	toField->setIgnored(fromField->isIgnored());
	toField->setDefault(fromField->isDefault());
	toField->fixCopy(copyConnections);
	if (fromField->isConnected() && copyConnections)
	    toField->copyConnection(fromField);
    }

    // Copy the kids
    for (i = 0; i < fromUnk->hiddenChildren.getLength(); i++) {

	// If this node is being copied, it must be "inside" (see
	// SoNode::copy() for details.) Therefore, all of its children
	// must be inside, as well, since our addToCopyDict() takes
	// care of that.
	SoNode *fromKid = fromUnk->getChild(i);
	SoNode *kidCopy = (SoNode *) findCopy(fromKid, copyConnections);

#ifdef DEBUG
	if (kidCopy == NULL)
	    SoDebugError::post("(internal) SoUnknownNode::copyContents",
			       "Child %d has not been copied yet", i);
#endif /* DEBUG */

	hiddenChildren.append(kidCopy);
    }

    // No need to copy the override flag, since this flag will have no
    // effect on an unknown node, and it is not read from or written
    // to files.
}