/*
	Copyright (c) 2024 PTC Inc. and/or Its Subsidiary Companies. All Rights Reserved.
*/


/*--------------------------------------------------------------------*\
Pro/TOOLKIT includes
\*--------------------------------------------------------------------*/
#include <ProToolkit.h>
#include <ProObjects.h>
#include <ProAssembly.h>
#include <ProAsmcomp.h>
#include <ProElemId.h>
#include <ProElement.h>
#include <ProExpldstate.h>
#include <ProFeatType.h>
#include <ProMdl.h>
#include <ProMessage.h>
#include <ProModelitem.h>
#include <ProMenu.h>
#include <ProSelection.h>
#include <ProSolid.h>
#include <ProUtil.h>
#include <ProValue.h>
#include <ProRefInfo.h>
#include <ProCopyGeom.h>

#include "TestError.h"
#include <ProTKRunTime.h>
#include <UtilMessage.h>

/*--------------------------------------------------------------------*\
Application macros
\*--------------------------------------------------------------------*/
#define UNUSED_MENU_INT 15000

/*--------------------------------------------------------------------*\
Application data types
\*--------------------------------------------------------------------*/


typedef enum {
    TEST_CHILDREN_GET = 0,
    TEST_PARENTS_GET = 1
} TestRels;

typedef enum {
    TEST_FEATURE_SELECT = 0,
    TEST_SOLID_SELECT = 1,
    TEST_SOLID_ALL_FEATS = 2,
    TEST_ALL_SOLIDS = 3,
    TEST_ALL_SOLIDS_ALL_FEATS = 4
} ExtrefinfoActionType;

typedef struct {
     ProExtRefType    type;
     ExtrefinfoActionType action_type;
     TestRels rels;
     ProBoolean solid;   /* solid/feature */
     FILE * qcr_ref;
} ExtrefinfoMenuState;


typedef struct {
    char * buttun_name;
    ProMenubuttonAction action;
    ProAppData data;
    int button_int;
} TestMenubuttonStruct;

typedef struct {
    char * menu_name;
	/*
    TestMenubuttonStruct *buttons;
	*/
    ProMenubuttonAction exit_action;
    ProAppData exit_data;
    int exit_button_int;
} TestMenuStruct;


/*--------------------------------------------------------------------*\
Application global/external data
\*--------------------------------------------------------------------*/


ProError ProTestSolidInfoWrite ( FILE * qcr_ref,  ProSolid solid);
int ProTestFileOpen (FILE ** qcr_ref);

/*====================================================================*\
  Function : ProTestCopiedRefSolidStateGet()
  Purpose  : 
\*====================================================================*/
ProError  ProTestCopiedRefSolidStateFilter(
    ProFeature * p_feat,
    ProAppData app_data)
{
    ProError err = PRO_TK_NO_ERROR;
    ProBoolean has_backup = PRO_B_TRUE;
    ProFeattype type;

    err = ProFeatureTypeGet (p_feat, &type);
    TEST_CALL_REPORT ("ProFeatureTypeGet()",
	"ProTestCopiedRefSolidStateFilter()", err ,
         err != PRO_TK_NO_ERROR);
    if (type == PRO_FEAT_GEOM_COPY)
    {
	return PRO_TK_NO_ERROR;
    }
    err = ProFeatureHasBackup (p_feat, &has_backup );
    TEST_CALL_REPORT ("ProFeatureHasBackup()",
	"ProTestCopiedRefSolidStateFilter()", err ,
         err != PRO_TK_NO_ERROR);
    
    if (err!=PRO_TK_NO_ERROR || has_backup == PRO_B_FALSE)
	return PRO_TK_CONTINUE; /* skip */
    return PRO_TK_NO_ERROR;
}

/*====================================================================*\
  Function : ProTestCopiedRefSolidStateVisitAction()
  Purpose  : 
\*====================================================================*/
ProError  ProTestCopiedRefSolidStateVisitAction(
    ProFeature * p_feat,
    ProError status,
    ProAppData app_data)
{
    ProError err = PRO_TK_NO_ERROR;
    FILE * qcr_ref = (FILE*) app_data;
    ProCopiedRefStateDetails f_state;
    ProSolid mdl;
    ProCharLine str;
    ProBoolean has_backup = PRO_B_TRUE;
    
    if (status != (ProError)PRO_FEAT_ACTIVE)
	return PRO_TK_NO_ERROR;

    ProTKSprintf (str,
	"New feature to get state \nid : %d type %d \n  owner : \n",
	p_feat->id,p_feat->type );
    ProTKFprintf (qcr_ref,"%s", str);
    ProUtilMsgPrint( "gen", "TEST %0s", str);

    err = ProModelitemMdlGet (p_feat, (ProMdl *) &mdl);
    TEST_CALL_REPORT ("ProModelitemMdlGet()",
	"ProTestCopiedRefSolidStateVisitAction()", err ,
         err != PRO_TK_NO_ERROR);

    err = ProTestSolidInfoWrite (qcr_ref, mdl);

    err = ProFeatureCopiedRefStateDetailsGet ( p_feat, & f_state);
    TEST_CALL_REPORT ("ProFeatureCopiedRefStateDetailsGet()",
	"ProTestCopiedRefSolidStateVisitAction()", err ,
         err != PRO_TK_NO_ERROR);

    err = ProFeatureHasBackup (p_feat, &has_backup );
    TEST_CALL_REPORT ("ProFeatureHasBackup()",
	"ProTestCopiedRefSolidStateVisitAction()", err ,
         err != PRO_TK_NO_ERROR);

    ProTKSprintf (str,
	"The feature state : %d backup : %d \n ",
        f_state, has_backup );
    ProTKFprintf (qcr_ref,"%s", str);
    ProUtilMsgPrint( "gen", "TEST %0s", str);

    return PRO_TK_NO_ERROR;
}

    
/*====================================================================*\
  Function : ProTestCopiedRefSolidStateGet()
  Purpose  : 
\*====================================================================*/
ProError  ProTestCopiedRefSolidStateGet(
    FILE * qcr_ref,
    ProSolid solid)
{
    ProError err = PRO_TK_NO_ERROR;

    err = ProSolidFeatVisit ( solid,
	(ProFeatureVisitAction) ProTestCopiedRefSolidStateVisitAction,
	(ProFeatureFilterAction)ProTestCopiedRefSolidStateFilter,
	(ProAppData) qcr_ref);
    TEST_CALL_REPORT ("ProSolidFeatVisit()",
	"ProTestCopiedRefSolidStateGet()", err ,
         err != PRO_TK_NO_ERROR);
    return err;
}
	
/*====================================================================*\
  Function : ProTestCopiedRefSolidSelectStateGet()
  Purpose  : Menu callback
\*====================================================================*/
int ProTestCopiedRefSolidSelectStateGet (ProAppData data, int dummy)
{
    ProError err;
    int n_sel;
    ProSelection *sel_prt;
    ProModelitem mdl;
    ProSolid solid;
    FILE * qcr_ref = *((FILE**) data);

    ProTestFileOpen (&qcr_ref);
    *((FILE**) data) = qcr_ref;
    
    err = ProSelect((char *)"prt_or_asm", 1, NULL, NULL, NULL, NULL, &sel_prt, &n_sel);
    if (n_sel < 1 || err  != PRO_TK_NO_ERROR)
	return 0;
    TEST_CALL_REPORT("ProSelect()", "ProTestCopiedRefSolidSelectStateGet()",
	    err, err != PRO_TK_NO_ERROR && err != PRO_TK_USER_ABORT &&
	    err != PRO_TK_PICK_ABOVE);
    err = ProSelectionModelitemGet (sel_prt[0], (ProModelitem*) &mdl);
    TEST_CALL_REPORT("ProSelectionModelitemGet()",
	"ProTestCopiedRefSolidSelectStateGet()",
	    err, err != PRO_TK_NO_ERROR);
	
    err = ProModelitemMdlGet ( &mdl, (ProMdl*) &solid);
    TEST_CALL_REPORT("ProModelitemMdlGet()",
	"ProTestCopiedRefSolidSelectStateGet()",
	    err, err != PRO_TK_NO_ERROR);

    err = ProTestCopiedRefSolidStateGet (qcr_ref, solid );

    return (0);
}

/*====================================================================*\
  Function : ProTestCopiedRefSolidAllGet()
  Purpose  : Menu buttun callback
\*====================================================================*/
int  ProTestCopiedRefSolidAllGet (ProAppData data, int dummy)
{
   ProError err;
   ProMdl *session_mdls;
   FILE * qcr_ref = *((FILE**) data);
   int arr_size = 0, i;

   ProTestFileOpen (&qcr_ref);
   *((FILE**) data) = qcr_ref;

   err = ProSessionMdlList (PRO_MDL_PART, & session_mdls, &arr_size);
   TEST_CALL_REPORT("ProSessionMdlList()", "ProTestCopiedRefSolidAllGet()",
				  err, err != PRO_TK_NO_ERROR);

   for (i = 0; i<arr_size; i++)
    {
	 err = ProTestCopiedRefSolidStateGet (qcr_ref, (ProSolid)session_mdls[i] );
	
    }
    err = ProArrayFree ((ProArray*)& session_mdls);
    TEST_CALL_REPORT("ProArrayFree()", "ProTestCopiedRefSolidAllGet()",
				  err, err != PRO_TK_NO_ERROR);
    
    return (0);
}

/*====================================================================*\
FUNCTION : ProTestSelectionDepndFilter
PURPOSE  : 
\*====================================================================*/
ProError ProTestSelectionDepndFilter(
    ProSelection selection,
    Pro3dPnt point,
    ProMatrix transform,
    char * option,
    int level,
    ProAppData app_data)
{
    ProFeature feat;
   
    ProError err = PRO_TK_NO_ERROR;
    ProBoolean has_backup = PRO_B_TRUE;
    ProFeattype type;

    err = ProSelectionModelitemGet ( selection, &feat);
    TEST_CALL_REPORT("ProSelectionModelitemGet()",
			         "ProTestSelectionDepndFilter()",
		     err, err != PRO_TK_NO_ERROR );

    err = ProFeatureTypeGet (&feat, &type);
    TEST_CALL_REPORT ("ProFeatureTypeGet()",
	"ProTestSelectionDepndFilter()", err ,
         err != PRO_TK_NO_ERROR);
    if (type == PRO_FEAT_GEOM_COPY)
    {

	return PRO_TK_NO_ERROR; /* accept */
    }

    err = ProFeatureHasBackup (&feat, &has_backup );
    TEST_CALL_REPORT ("ProFeatureHasBackup()",
	"ProTestSelectionDepndFilter()", err ,
         err != PRO_TK_NO_ERROR);
	
    if (err!=PRO_TK_NO_ERROR || has_backup == PRO_B_FALSE)
	return PRO_TK_CONTINUE; /* skip */
    return PRO_TK_NO_ERROR; /* accept */
   

}


/*====================================================================*\
  Function : ProTestCopiedRefDependSet()
  Purpose  : Menu callback
\*====================================================================*/
int ProTestCopiedRefDependSet (ProAppData data, int dummy)
{
    ProError err;
    int n_sel;
    ProSelection *sel_feat;
    ProFeature feat;
    ProSelFunctions sel_funcs;

    sel_funcs.pre_filter = (ProSelectionPreFilter)ProTestSelectionDepndFilter;

    sel_funcs.post_filter =  NULL;
    sel_funcs.post_selact = NULL;
    sel_funcs.app_data = NULL;
    
    err = ProSelect((char *)"feature", 1, NULL,&sel_funcs , NULL, NULL, &sel_feat, &n_sel);
    if (n_sel < 1 || err  != PRO_TK_NO_ERROR)
	return 0;
    TEST_CALL_REPORT("ProSelect()", "ProTestCopiedRefDependSet()",
	    err, err != PRO_TK_NO_ERROR && err != PRO_TK_USER_ABORT &&
	    err != PRO_TK_PICK_ABOVE);
    err = ProSelectionModelitemGet (sel_feat[0], (ProModelitem*) &feat);
    TEST_CALL_REPORT("ProSelectionModelitemGet()",
	"ProTestCopiedRefDependSet()",
	    err, err != PRO_TK_NO_ERROR);
	
    err = ProFeatureDSFDependencystateSet (&feat, PRO_DSF_UPDATE_AUTOMATICALLY);
    TEST_CALL_REPORT("ProFeatureDSFDependencystateSet()",
	"ProTestCopiedRefDependSet()",
	    err, err != PRO_TK_NO_ERROR);
	
    return (0);
}


/*====================================================================*\
  Function : ProTestCopiedRefInDependSet()
  Purpose  : Menu callback
\*====================================================================*/
int ProTestCopiedRefInDependSet (ProAppData data, int dummy)
{
    ProError err;
    int n_sel;
    ProSelection *sel_feat;
    ProFeature feat;
    ProSelFunctions sel_funcs;

    sel_funcs.pre_filter = (ProSelectionPreFilter)ProTestSelectionDepndFilter;

    sel_funcs.post_filter =  NULL;
    sel_funcs.post_selact = NULL;
    sel_funcs.app_data = NULL;
    
    err = ProSelect((char *)"feature", 1, NULL,&sel_funcs , NULL, NULL, &sel_feat, &n_sel);
    if (n_sel < 1 || err  != PRO_TK_NO_ERROR)
	return 0;
    TEST_CALL_REPORT("ProSelect()", "ProTestCopiedRefInDependSet()",
	    err, err != PRO_TK_NO_ERROR && err != PRO_TK_USER_ABORT &&
	    err != PRO_TK_PICK_ABOVE);
    err = ProSelectionModelitemGet (sel_feat[0], (ProModelitem*) &feat);
    TEST_CALL_REPORT("ProSelectionModelitemGet()",
	"ProTestCopiedRefInDependSet()",
	    err, err != PRO_TK_NO_ERROR);
	
    err = ProFeatureDSFDependencystateSet (&feat, PRO_DSF_UPDATE_MANUALLY);
    TEST_CALL_REPORT("ProFeatureDSFDependencystateSet()",
	"ProTestCopiedRefInDependSet()",
	    err, err != PRO_TK_NO_ERROR);
	
    return (0);
}

/*--------------------------------------------------------------------*/

/*====================================================================*\
  Function : ProTestExtFeatRefProcess()
  Purpose  : 
\*====================================================================*/
ProError  ProTestExtFeatRefProcess(
    FILE * qcr_ref,
    ProExtFeatRef ref)
{
    ProError err = PRO_TK_NO_ERROR;
    ProRefState state = PRO_REF_ACTIVE;
    ProType type;
    ProAsmcomppath own_comp, ref_comp;
    ProSolid solid;
    ProFeature feature;
    ProModelitem modelitem;
    int i;

    own_comp.table_num = ref_comp.table_num = 0;
    feature.type = PRO_TYPE_UNUSED;
    modelitem.type = PRO_TYPE_UNUSED;

    err = ProExtRefStateGet ( ref, &state);
    TEST_CALL_REPORT ("ProExtRefStateGet()",
	"ProTestExtFeatRefProcess()", err ,
         err != PRO_TK_NO_ERROR);

    ProTKFprintf (qcr_ref, "Reference state : %d\n", state);

    err = ProExtRefTypeGet ( ref, &type);
    TEST_CALL_REPORT ("ProExtRefTypeGet()",
	"ProTestExtFeatRefProcess()", err ,
         err != PRO_TK_NO_ERROR);
    
    ProTKFprintf (qcr_ref, "Reference type : %d\n", type);

    err = ProExtRefAsmcompsGet (ref, &own_comp, &ref_comp);
    TEST_CALL_REPORT ("ProExtRefAsmcompsGet()",
	"ProTestExtFeatRefProcess()", err ,
         err != PRO_TK_NO_ERROR);

    if (ref_comp.table_num != 0)
    {
	ProTKFprintf (qcr_ref, "owner's asmcomppath model:\n");
	err = ProTestSolidInfoWrite (qcr_ref, own_comp.owner);
	ProTKFprintf (qcr_ref, "Reference's asmcomppath model:\n");
        err = ProTestSolidInfoWrite (qcr_ref, ref_comp.owner);
    }

    ProTKFprintf (qcr_ref, "Owner's asmcomppath:\n");
    for (i=0; i<own_comp.table_num; i++)
	ProTKFprintf (qcr_ref, "%d ", own_comp.comp_id_table[i]);
    
    ProTKFprintf (qcr_ref, "\nReference's asmcomppath:\n");
    for (i=0; i<ref_comp.table_num; i++)
	ProTKFprintf (qcr_ref, "%d ", ref_comp.comp_id_table[i]);

    err = ProExtRefOwnMdlGet (ref, &solid);
    TEST_CALL_REPORT ("ProExtRefOwnMdlGet()",
	"ProTestExtFeatRefProcess()", err ,
         err != PRO_TK_NO_ERROR);
    ProTKFprintf (qcr_ref, "\nOwner model:\n");
    err = ProTestSolidInfoWrite (qcr_ref, solid);

     err = ProExtRefMdlGet (ref, &solid);
    TEST_CALL_REPORT ("ProExtRefMdlGet()",
	"ProTestExtFeatRefProcess()", err ,
         err != PRO_TK_NO_ERROR);
   	ProTKFprintf (qcr_ref, "Reference model:\n");
	err = ProTestSolidInfoWrite (qcr_ref, solid); 
	
    err = ProExtRefOwnFeatGet (ref, &feature);
    TEST_CALL_REPORT ("ProExtRefOwnFeatGet()",
	"ProTestExtFeatRefProcess()", err ,
         err != PRO_TK_NO_ERROR);
    if (feature.type != PRO_TYPE_UNUSED)
    {
	ProTKFprintf (qcr_ref, "Owner feature ID: %d\n", feature.id);
	ProTKFprintf (qcr_ref, "Owner feature type: %d\n", feature.type);
        err = ProTestSolidInfoWrite (qcr_ref, (ProSolid)feature.owner);
    }

    err = ProExtRefFeatGet (ref, &feature);
    TEST_CALL_REPORT ("ProExtRefFeatGet()",
	"ProTestExtFeatRefProcess()", err ,
         err != PRO_TK_NO_ERROR);
    if (feature.type != PRO_TYPE_UNUSED)
    {
	ProTKFprintf (qcr_ref, "Reference feature ID: %d\n", feature.id);
	ProTKFprintf (qcr_ref, "Reference feature type: %d\n", feature.type);
        err = ProTestSolidInfoWrite (qcr_ref, (ProSolid)feature.owner);
    }

    err = ProExtRefModelitemGet (ref, &modelitem);
    TEST_CALL_REPORT ("ProExtRefModelitemGet()",
	"ProTestExtFeatRefProcess()", err ,
         err != PRO_TK_NO_ERROR);
    if (modelitem.type != PRO_TYPE_UNUSED)
    {
	ProTKFprintf (qcr_ref, "Reference modelitem ID: %d\n", modelitem.id);
	ProTKFprintf (qcr_ref, "Reference modelitem type: %d\n", modelitem.type);
        err = ProTestSolidInfoWrite (qcr_ref, (ProSolid)modelitem.owner);
    }

    return (err);
}


/*====================================================================*\
  Function : ProTestRefExtInfoProcess()
  Purpose  : 
\*====================================================================*/
ProError ProTestRefExtInfoProcess (
    FILE * qcr_ref,
    ProExtRefInfo * info)
{
    ProError err = PRO_TK_NO_ERROR;
    int i;

    ProTKFprintf (qcr_ref,"Ext. ref. info : type %d n_refs : %d\n",
	info->type, info->n_refs);

    for (i = 0; i< info->n_refs; i++)
    {
	ProTKFprintf (qcr_ref,"the number of ProExtFeatRef item : %d \n", i);
	err = ProTestExtFeatRefProcess (qcr_ref, info->ext_refs[i]);
    }

    ProTKFprintf (qcr_ref,"End of ext. ref. info\n");
    return (err);
}

/*====================================================================*\
  Function : ProTestRefExtIfoArrProcess()
  Purpose  : 
\*====================================================================*/
ProError ProTestRefExtIfoArrProcess (
    FILE * qcr_ref,
    ProExtRefInfo * infos,
    int n_infos)
{
    ProError err = PRO_TK_NO_ERROR;
    int i;

    for (i = 0; i< n_infos; i++)
	err = ProTestRefExtInfoProcess (qcr_ref, &(infos[i]));
	
    return (err);
}


/*====================================================================*\
  Function : ProTestFeatureExternGet()
  Purpose  : 
\*====================================================================*/
ProError ProTestFeatureExternGet (
    ProFeature * feature,
    ProExtRefType type,
    ProExtRefInfo ** infos,
    int * n_infos,
    TestRels rel)
{
    ProError err = PRO_TK_NO_ERROR;

    
    if (rel == TEST_CHILDREN_GET)
    {
	  
	err = ProFeatureExternChildrenGet (feature, type, infos, n_infos);
	TEST_CALL_REPORT("ProFeatureExternChildrenGet()",
	"ProTestFeatureExternGet()",
	    err, err != PRO_TK_NO_ERROR);
	   
    }
    else
    {
	   
	err = ProFeatureExternParentsGet (feature, type, infos, n_infos);
	TEST_CALL_REPORT("ProFeatureExternParentsGet()",
	"ProTestFeatureExternGet()",
	    err, err != PRO_TK_NO_ERROR);
	   
    }
	


    return (err);
}

/*====================================================================*\
  Function : ProTestSolidExternGet()
  Purpose  : 
\*====================================================================*/
ProError ProTestSolidExternGet (
    ProSolid solid,
    ProExtRefType type,
    ProExtRefInfo ** infos,
    int * n_infos,
    TestRels rel)
{
    ProError err = PRO_TK_NO_ERROR;
     
    if (rel == TEST_CHILDREN_GET)
    {
	    
	err = ProSolidExternChildrenGet (solid, type, infos, n_infos);
	TEST_CALL_REPORT("ProSolidExternChildrenGet()",
	"ProTestFeatureExternGet()",
	    err, err != PRO_TK_NO_ERROR);
	   
    }
    else
    {
	   
	err = ProSolidExternParentsGet (solid, type, infos, n_infos);
	TEST_CALL_REPORT("ProSolidExternParentsGet()",
	"ProTestFeatureExternGet()",
	    err, err != PRO_TK_NO_ERROR);
	    
    }
	


    return (err);
}

/*====================================================================*\
  Function : ProTestFeatuteExtrefinfo()
  Purpose  : 
\*====================================================================*/
ProError ProTestFeatuteExtrefinfo (
    FILE * qcr_ref,
    ProExtRefType type,
    ProFeature * feature,
    TestRels rel)
{
    ProError err = PRO_TK_NO_ERROR;
    ProExtRefInfo * infos = NULL;
    int n_infos;

    ProTKFprintf (qcr_ref, "Proccess a new feature. ID is : %d, Type is %d\n",
	feature->type, feature->id);

    err = ProTestFeatureExternGet (feature, type, &infos, &n_infos, rel);
    if (err != PRO_TK_NO_ERROR)
	return err;
    
    err = ProTestRefExtIfoArrProcess (qcr_ref, infos, n_infos );
       
    err = ProExtRefInfoFree ( &infos);
    TEST_CALL_REPORT("ProExtRefInfoFree()",
	"ProTestFeatuteExtrefinfo()",
	    err, err != PRO_TK_NO_ERROR); 
       
    return (err);
}

/*====================================================================*\
  Function : ProTestSolidExtrefinfo()
  Purpose  : 
\*====================================================================*/
ProError ProTestSolidExtrefinfo (
    FILE * qcr_ref,
    ProExtRefType type,
    ProSolid solid,
    TestRels rel)
{
    ProError err = PRO_TK_NO_ERROR;
    ProExtRefInfo * infos=NULL;
    int n_infos;

    ProTKFprintf (qcr_ref, "Proccess a new solid. Ref. type : %d", type);
    if (rel ==TEST_CHILDREN_GET)
	ProTKFprintf (qcr_ref," Getting children... \n\n");
    else
	ProTKFprintf (qcr_ref," Getting parents... \n\n");
    err = ProTestSolidInfoWrite (qcr_ref, solid);

    err = ProTestSolidExternGet (solid, type, &infos, &n_infos, rel);
    if (err != PRO_TK_NO_ERROR)
	return err;
    
    err = ProTestRefExtIfoArrProcess (qcr_ref, infos, n_infos );
	
    err = ProExtRefInfoFree ( &infos);
    TEST_CALL_REPORT("ProExtRefInfoFree()",
	"ProTestSolidExtrefinfo()",
	    err, err != PRO_TK_NO_ERROR);
    ProTKFprintf (qcr_ref, "\nEnd\n\n");
    
    return (err);
}

/*====================================================================*\
  Function : ProTestFeatuteSelectExtrefinfo()
  Purpose  : 
\*====================================================================*/
ProError ProTestFeatuteSelectExtrefinfo (
    FILE * qcr_ref,
    ProExtRefType type,
    TestRels rel)
{
    ProError err = PRO_TK_NO_ERROR;
    int n_sel;
    ProSelection *sel_feat;
    ProFeature feat; 

err = ProSelect((char *)"feature", 1, NULL, NULL, NULL, NULL, &sel_feat, &n_sel);
    if (n_sel < 1 || err  != PRO_TK_NO_ERROR)
	return PRO_TK_NO_ERROR;
    TEST_CALL_REPORT("ProSelect()", "ProTestFeatuteSelectExtrefinfo()",
	    err, err != PRO_TK_NO_ERROR && err != PRO_TK_USER_ABORT &&
	    err != PRO_TK_PICK_ABOVE);
    
    err = ProSelectionModelitemGet ( sel_feat[0], &feat);
    TEST_CALL_REPORT("ProSelectionModelitemGet()",
			         "ProTestFeatuteSelectExtrefinfo()",
		     err, err != PRO_TK_NO_ERROR );    
    
    err = ProTestFeatuteExtrefinfo (qcr_ref, type,  &feat, rel);
    return err;
}





/*====================================================================*\
  Function : ProTestSolidSelectExtrefinfo()
  Purpose  : 
\*====================================================================*/
ProError ProTestSolidSelectExtrefinfo (
    FILE * qcr_ref,
    ProExtRefType type,
    TestRels rel)
{
    ProError err = PRO_TK_NO_ERROR;
    int n_sel;
    ProSelection *sel_feat;
    ProModelitem modelitem;
    ProSolid solid;

    err = ProSelect((char *)"prt_or_asm", 1, NULL, NULL, NULL, NULL, &sel_feat, &n_sel);
    if (n_sel < 1 || err  != PRO_TK_NO_ERROR)
	return PRO_TK_NO_ERROR;
    TEST_CALL_REPORT("ProSelect()", "ProTestSolidSelectExtrefinfo()",
	    err, err != PRO_TK_NO_ERROR && err != PRO_TK_USER_ABORT &&
	    err != PRO_TK_PICK_ABOVE);
    
    err = ProSelectionModelitemGet ( sel_feat[0], &modelitem);
    TEST_CALL_REPORT("ProSelectionModelitemGet()",
			         "ProTestSolidSelectExtrefinfo()",
		     err, err != PRO_TK_NO_ERROR );
    
    err = ProModelitemMdlGet ( &modelitem, (ProMdl*) &solid);
    TEST_CALL_REPORT("ProModelitemMdlGet()",
	"ProTestSolidSelectExtrefinfo()",
	    err, err != PRO_TK_NO_ERROR);
    
    err = ProTestSolidExtrefinfo (qcr_ref, type,  solid, rel);
    return err;
}

/*====================================================================*\
  Function : ProTestSolidExtrefinfoVisitAction()
  Purpose  : 
\*====================================================================*/
ProError  ProTestSolidExtrefinfoVisitAction(
    ProFeature * p_feat,
    ProError status,
    ProAppData app_data)
{
    ExtrefinfoMenuState *st = (ExtrefinfoMenuState*) app_data;
    
    ProTestFeatuteExtrefinfo (st->qcr_ref, st->type,  p_feat, st->rels);

    return PRO_TK_NO_ERROR;
}

/*====================================================================*\
  Function : ProTestSolidAllfeatExtrefinfo()
  Purpose  : 
\*====================================================================*/
ProError  ProTestSolidAllfeatExtrefinfo(
    FILE * qcr_ref,
    ProExtRefType type,
    TestRels rel)

{
    ProError err = PRO_TK_NO_ERROR;
    int n_sel;
    ProSelection *sel_feat;
    ProModelitem modelitem;
    ProSolid solid;
    ExtrefinfoMenuState st;
    
    st.type = type;
    st.rels = rel;
    st.qcr_ref = qcr_ref;
    

    err = ProSelect((char *)"prt_or_asm", 1, NULL, NULL, NULL, NULL, &sel_feat, &n_sel);
    if (n_sel < 1 || err  != PRO_TK_NO_ERROR)
	return PRO_TK_NO_ERROR;
    TEST_CALL_REPORT("ProSelect()", "ProTestSolidAllfeatExtrefinfo()",
	    err, err != PRO_TK_NO_ERROR && err != PRO_TK_USER_ABORT &&
	    err != PRO_TK_PICK_ABOVE);
    
    err = ProSelectionModelitemGet ( sel_feat[0], &modelitem);
    TEST_CALL_REPORT("ProSelectionModelitemGet()",
			         "ProTestSolidAllfeatExtrefinfo()",
		     err, err != PRO_TK_NO_ERROR );
    
    err = ProModelitemMdlGet ( &modelitem, (ProMdl*) &solid);
    TEST_CALL_REPORT("ProModelitemMdlGet()",
	"ProTestSolidAllfeatExtrefinfo()",
	    err, err != PRO_TK_NO_ERROR);

    err = ProSolidFeatVisit ( solid,
	(ProFeatureVisitAction) ProTestSolidExtrefinfoVisitAction,
	NULL,
	(ProAppData) &st);
    TEST_CALL_REPORT ("ProSolidFeatVisit()",
	"ProTestSolidAllfeatExtrefinfo()", err ,
         err != PRO_TK_NO_ERROR);
    return err;
}

/*====================================================================*\
  Function : ProTestAllSolidExtrefinfo()
  Purpose  : 
\*====================================================================*/
ProError  ProTestAllSolidExtrefinfo(
    FILE * qcr_ref,
    ProExtRefType type,
    TestRels rel)

{
    ProError err = PRO_TK_NO_ERROR;
    ProMdl *session_mdls;
   int arr_size = 0, i;

   err = ProSessionMdlList (PRO_MDL_PART, & session_mdls, &arr_size);
   TEST_CALL_REPORT("ProSessionMdlList()", "ProTestAllSolidExtrefinfo()",
				  err, err != PRO_TK_NO_ERROR);

   for (i = 0; i<arr_size; i++)
    {
	err = ProTestSolidExtrefinfo (qcr_ref, type,
	    (ProSolid) session_mdls[i], rel);
	
    }
    err = ProArrayFree ((ProArray*)& session_mdls);
    TEST_CALL_REPORT("ProArrayFree()", "ProTestAllSolidExtrefinfo()",
				  err, err != PRO_TK_NO_ERROR);
    
    return (err);
}

/*====================================================================*\
  Function : ProTestAllSolidAllfeatExtrefinfo()
  Purpose  : 
\*====================================================================*/
ProError  ProTestAllSolidAllfeatExtrefinfo(
    FILE * qcr_ref,
    ProExtRefType type,
    TestRels rel)

{
    ProError err = PRO_TK_NO_ERROR;
    ProMdl *session_mdls;
   int arr_size = 0, i;
   ExtrefinfoMenuState st;
    
    st.type = type;
    st.rels = rel;
    st.qcr_ref = qcr_ref;

   err = ProSessionMdlList (PRO_MDL_PART, & session_mdls, &arr_size);
   TEST_CALL_REPORT("ProSessionMdlList()","ProTestAllSolidAllfeatExtrefinfo()",
				  err, err != PRO_TK_NO_ERROR);

   for (i = 0; i<arr_size; i++)
    {
	
	err = ProSolidFeatVisit ( (ProSolid) session_mdls[i],
	(ProFeatureVisitAction) ProTestSolidExtrefinfoVisitAction,
	NULL,
	(ProAppData) &st);
         TEST_CALL_REPORT ("ProSolidFeatVisit()",
	"ProTestAllSolidAllfeatExtrefinfo()", err ,
         err != PRO_TK_NO_ERROR);
	
    }
    err = ProArrayFree ((ProArray*)& session_mdls);
    TEST_CALL_REPORT("ProArrayFree()", "ProTestAllSolidAllfeatExtrefinfo()",
				  err, err != PRO_TK_NO_ERROR);
    
    return (err);
}


/*====================================================================*\
  Function : ProTestExtrefinfoActionProccess()
  Purpose  : Menu callback
\*====================================================================*/
int ProTestExtrefinfoActionProccess (ProAppData data, int dummy)
{
    ExtrefinfoMenuState *st = (ExtrefinfoMenuState*) data;

    switch (st->action_type)
    {
	case TEST_FEATURE_SELECT:
	    ProTestFeatuteSelectExtrefinfo (st->qcr_ref,
		st->type, st->rels);
	    break;
	case TEST_SOLID_SELECT:
	    ProTestSolidSelectExtrefinfo (st->qcr_ref,
		st->type, st->rels);
	    break;
	case TEST_SOLID_ALL_FEATS:
	    ProTestSolidAllfeatExtrefinfo(st->qcr_ref,
		st->type, st->rels);
	    break;
	case TEST_ALL_SOLIDS:
	    ProTestAllSolidExtrefinfo (st->qcr_ref,
		st->type, st->rels);
	    break;
	case TEST_ALL_SOLIDS_ALL_FEATS:
	    ProTestAllSolidAllfeatExtrefinfo (st->qcr_ref,
		st->type, st->rels);
	    break;
    }

    
    return (0);
}

/*====================================================================*\
  Function : ProTestMenuSetup()
  Purpose  : 
\*====================================================================*/
ProError  ProTestMenuSetup (
    TestMenuStruct * menu,
    ProMenubuttonAction action,
    ProAppData data,
    int button_int,
    TestMenubuttonStruct *buttons,
    char * menu_name)
{
    ProError err;
    int i, size, id;
    wchar_t ** names;

    for (i=0;;i++)
	if(strcmp (buttons[i].buttun_name, "") == 0)
	    break;

    
    size = i;
    names = (wchar_t**)calloc(size+1, sizeof(wchar_t*));
    
    for (i=0; i<=size; i++)
    {
	names[i] = (wchar_t*)calloc(PRO_NAME_SIZE, sizeof(wchar_t));
	ProStringToWstring(names[i], buttons[i].buttun_name );
    }

    err = ProMenuFromStringsRegister(menu_name, NULL, names, NULL, 
	    NULL, &id);

    TEST_CALL_REPORT("ProMenuFromStringsRegister()", "ProTestMenuSetup()",
	    err, err != PRO_TK_NO_ERROR);

    for (i=0; i<size+1; i++)
	free(names[i]);
    
    free(names);

    for (i=0; i<=size; i++)
    {
    	ProMenubuttonActionSet(menu_name, buttons[i].buttun_name,
	  ((buttons[i].action == NULL)? action : buttons[i].action),
	    ((buttons[i].data == NULL)? data : buttons[i].data),
	    ((buttons[i].button_int == UNUSED_MENU_INT ) ?button_int :
	           buttons[i].button_int));
    }


    ProMenubuttonActionSet(menu_name ,menu_name,
	 menu->exit_action, menu->exit_data, menu->exit_button_int);
    return err;
}

/*====================================================================*\
  Function : ()
  Purpose  : 
\*====================================================================*/
int ProTestCompmenuQuit(ProAppData p_member, int option)
{
    ProError status;

    status = ProMenuDelete();
    status = ProMenuDelete();
    status = ProMenuDelete();
    status = ProMenuDelete();

    TEST_CALL_REPORT("ProMenuDelete()","ProTestDoneCancelAssign()", status,
    				status != PRO_TK_NO_ERROR);
    
    return (0);
}

int ProTestScopeAssign(ProAppData p_member, int option);

/*====================================================================*\
  Function : ProTestExtrefinfoMenuAction()
  Purpose  : Menu callback
\*====================================================================*/
int  ProTestExtrefinfoMenuAction (ProAppData data, int dummy)
{
    ProError err;
    ExtrefinfoMenuState st;
    int dummyx;
    static char * menus[] = {"Relation", "Act. Type", "Ref. Type",
			     "ProcExit", ""};
    TestMenubuttonStruct ch_par_buttons [] =
    {
	{
	    (char *)"Get Children",
	     (ProMenubuttonAction)ProTestScopeAssign,
	      NULL,
	     (int)TEST_CHILDREN_GET
	},
	{
	    (char *)"Get Parents",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)TEST_PARENTS_GET
	},
	{
	    (char *)"",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)TEST_PARENTS_GET
	}
    };
    
    TestMenuStruct RelMenu = {
	NULL,
        (ProMenubuttonAction)ProMenuDelete,
        NULL,
        0
    };

    TestMenubuttonStruct action_type_buttons [] =
    {
	{
	    (char *)"Feat Select",
	     (ProMenubuttonAction)ProTestScopeAssign,
	      NULL,
	     (int)TEST_FEATURE_SELECT
	},
	{
	    (char *)"Solid Select",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)TEST_SOLID_SELECT
	},
	{
	    (char *)"All Feat in Solid",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)TEST_SOLID_ALL_FEATS
	},
	{
	    (char *)"All Solids",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)TEST_ALL_SOLIDS
	},
	{
	    (char *)"All Feats in All Solids",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)TEST_ALL_SOLIDS_ALL_FEATS
	},
	{
	    (char *)"",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)TEST_ALL_SOLIDS_ALL_FEATS
	}
    };
     TestMenuStruct ActTypeMenu = {
	NULL,
        (ProMenubuttonAction)ProMenuDelete,
        NULL,
        0
    };

    TestMenubuttonStruct ext_ref_type_buttons [] =
    {
	{
	    (char *)"PRO_EXT_GEOM_REF",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)PRO_EXT_GEOM_REF
	},
	{
	    (char *)"PRO_LOC_GEOM_REF",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)PRO_LOC_GEOM_REF
	},
	{
	    (char *)"PRO_MERGE_REF",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)PRO_MERGE_REF
	},
	{
	    (char *)"PRO_EXT_REL_REF",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)PRO_EXT_REL_REF
	},
	{
	    (char *)"PRO_LOC_REL_REF",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)PRO_LOC_REL_REF
	},
	{
	    (char *)"PRO_PRGM_REF",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)PRO_PRGM_REF
	},
	{
	    (char *)"PRO_MOVE_COMP_REF",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)PRO_MOVE_COMP_REF
	},
	{
	    (char *)"PRO_SUBS_REF",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)PRO_SUBS_REF
	},
	{
	    (char *)"PRO_MFG_INFO_REF",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)PRO_MFG_INFO_REF
	},
	{
	    (char *)"PRO_INTRCH_REF",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)PRO_INTRCH_REF
	},
	{
	    (char *)"PRO_HARN_REF",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)PRO_HARN_REF
	},
	{
	    (char *)"PRO_FEAT_PAT_REF",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)PRO_FEAT_PAT_REF
	},
	{
	    (char *)"PRO_ALL_EXT_REF_TYPES",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)PRO_ALL_EXT_REF_TYPES
	},
	{
	    (char *)"PRO_ALL_REF_TYPES",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)PRO_ALL_REF_TYPES
	},
	{
	    (char *)"",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     (int)PRO_ALL_REF_TYPES
	}
    };

    TestMenuStruct RefTypeMenu = {
	NULL,
        (ProMenubuttonAction)ProMenuDelete,
        NULL,
        0
    };

    TestMenubuttonStruct exit_proc_buttons [] =
    {
	{
	    (char *)"Proccess",
	     (ProMenubuttonAction)ProTestExtrefinfoActionProccess,
	     NULL,
	     0
	},
	{
	    (char *)"Quit",
	     (ProMenubuttonAction)ProTestCompmenuQuit,
	     NULL,
	     0
	},
	{
	    (char *)"",
	     (ProMenubuttonAction)ProTestScopeAssign,
	     NULL,
	     0
	}
    };

     TestMenuStruct ExitProcMenu = {
	NULL,
        (ProMenubuttonAction)ProMenuDelete,
        NULL,
        0
    };

    st.qcr_ref = *((FILE**) data);
    ProTestFileOpen (&(st.qcr_ref));
    *((FILE**) data) = st.qcr_ref;


    ProTestMenuSetup (&RelMenu, (ProMenubuttonAction) NULL,
	(ProAppData)&(st.rels), 0, ch_par_buttons, menus[0]);
    
    ProTestMenuSetup (&ActTypeMenu, (ProMenubuttonAction) NULL,
	(ProAppData)&(st.action_type), 0, action_type_buttons, menus[1]);
    
    ProTestMenuSetup (&RefTypeMenu, (ProMenubuttonAction) NULL,
	(ProAppData)&(st.type), 0, ext_ref_type_buttons, menus[2]);
    
    ProTestMenuSetup (&ExitProcMenu, (ProMenubuttonAction) NULL,
	(ProAppData) &st, 0, exit_proc_buttons, menus[3]);



    err = ProCompoundmenuCreate(menus, &dummyx);
    TEST_CALL_REPORT ("ProCompoundmenuCreate()","ProTestExtrefinfoMenuAction()",
	 err ,
         err != PRO_TK_NO_ERROR);

     err = ProMenuProcess(menus[0], &dummyx);
     TEST_CALL_REPORT ("ProMenuProcess()", 
                   "ProTestExtrefinfoMenuAction()",
	           err, err != PRO_TK_NO_ERROR);
     return (PRO_TK_NO_ERROR);
}