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


/*--------------------------------------------------------------------*\
Pro/Toolkit  includes
\*--------------------------------------------------------------------*/
#include <ProToolkit.h>
#include <ProElement.h>
#include <ProFeature.h>
#include <ProFeatType.h>
#include <ProMenu.h>
#include <ProModelitem.h>
#include <ProNcseq.h>
#include <ProNcseqElem.h>
#include <ProClCmd.h>
#include <ProClcmdElem.h>
#include <ProSelection.h>
#include <ProUtil.h>
#include <ProTKRunTime.h>
#include <PTApplsUnicodeUtils.h>

/*--------------------------------------------------------------------*\
Application includes
\*--------------------------------------------------------------------*/
#include "TestError.h"
#include "TestConsts.h"
#include "TestMfgNew.h"
#include "UtilMessage.h"
#include "UtilGroups.h"

/*--------------------------------------------------------------------*\
Application types
\*--------------------------------------------------------------------*/
typedef  enum {
    TEST_NCL_CREATE = 0,
	TEST_NCL_REMOVE,
	TEST_NCL_REMOVE_BY_IDX,
	TEST_NCL_REDEFINE,
    TEST_NCL_REDEFINE_BY_IDX
} TestNclActType ;



typedef struct usr_elem_table{
    int elem_type;
    int val_type;
} UserElemTable;


#define TEST_NCLC_CREATE 0
#define TEST_NCLC_RECREATE 1
#define TEST_NCLC_REDEFINE 2


/*--------------------------------------------------------------------*\
Function prototypes
\*--------------------------------------------------------------------*/
ProError ProTestCmdsArrayFree (wchar_t*** cmds);
ProError ProTestClcmdElemCreate( ProElement NclCmds)  ;
ProError ProTestClcmdElemRemove(    ProElement elem_tree) ;
ProError ProTestClcmdElemRemoveByIndex(    ProElement elem_tree);
ProError ProTestClcmdElemRedefineByIndex(    ProElement elem_tree);
ProError ProTestClcmdElemRedefine(    ProElement elem_tree);
int ProTestCustmzRecreate( void* p_dummy,     int action );
int ProTestCustmzRedefine(  void* p_dummy,     int action );
int ProTestCustmzCreateMenuAct(void* p_dummy, int action );

/*====================================================================*\
FUNCTION : ProTestPrintErrs
PURPOSE  : print feature creation or redefinition errors
\*====================================================================*/
ProError ProTestRootToNclcommElem (
    ProElement tree_root,
    ProElement * NclcommsElem)
{
    ProError err;
    ProElempath to_ncl_cmds;
    ProElempathItem path = {
	PRO_ELEM_PATH_ITEM_TYPE_ID,
	PRO_E_NCL_COMMANDS
    };
    ProElemId id;

    err = ProElementIdGet (tree_root, &id);
    TEST_CALL_REPORT("ProElementIdGet()",
			         "ProTestRootToNclcommElem()",
		     err, err != PRO_TK_NO_ERROR );
    
    if (id == PRO_E_NCL_COMMANDS)
    {
	*NclcommsElem = tree_root;
	return PRO_TK_NO_ERROR;
    }
	

    err = ProElempathAlloc ( &to_ncl_cmds);
    TEST_CALL_REPORT("ProElempathAlloc()",
			         "ProTestRootToNclcommElem()",
		     err, err != PRO_TK_NO_ERROR );

    err = ProElempathDataSet ( to_ncl_cmds, &path, 1);
    TEST_CALL_REPORT("ProElempathDataSet()",
			         "ProTestRootToNclcommElem()",
		     err, err != PRO_TK_NO_ERROR );

    err = ProElemtreeElementGet (tree_root, to_ncl_cmds, NclcommsElem);
    TEST_CALL_REPORT("ProElemtreeElementGet()",
			         "ProTestRootToNclcommElem()",
		     err, err != PRO_TK_NO_ERROR );
    
    err = ProElementIdGet (*NclcommsElem, &id);
    TEST_CALL_REPORT("ProElementIdGet()",
			         "ProTestRootToNclcommElem()",
		     err, err != PRO_TK_NO_ERROR );
    ProTKPrintf ((char*)"Id: %d\n", id);
    
    err = ProElempathFree ( &to_ncl_cmds);
    TEST_CALL_REPORT("ProElempathFree()",
			         "ProTestRootToNclcommElem()",
		     err, err != PRO_TK_NO_ERROR );


    return (err);
}
/*====================================================================*\
FUNCTION : ProTestChooseNclAct
PURPOSE  : Select 
\*====================================================================*/
int ProTestChooseNclAct(
    ProElement custm_tree, 
    int opt )
{
    ProError err;

    switch (opt)
    {
	case TEST_NCL_CREATE:
	    err = ProTestClcmdElemCreate(custm_tree);
	    break;
	case TEST_NCL_REMOVE:
	    err = ProTestClcmdElemRemove(custm_tree);
	    break;
	case TEST_NCL_REMOVE_BY_IDX:
	    err = ProTestClcmdElemRemoveByIndex(custm_tree);
	    break;
	case TEST_NCL_REDEFINE:
	    err = ProTestClcmdElemRedefine(custm_tree);
	    break;
	case TEST_NCL_REDEFINE_BY_IDX:
	    err = ProTestClcmdElemRedefineByIndex(custm_tree);
	    break;
	default:
	    ProTKPrintf((char*)"error in data\n");
    }
    
    return (0);
}

    
/*====================================================================*\
FUNCTION : ProTest
PURPOSE  : Select 
\*====================================================================*/
int ProTestTkClcmdsAct (ProAppData data, int dummy)
{
    ProError err;
    int menu_id;
    int opt;
    
    
    err = ProMenuFileRegister( (char*)"TkCLcmds", (char*)"tkclcmds.mnu", &menu_id );
    TEST_CALL_REPORT( "ProMenuFileRegister()", "ProTestAsmFunc()",
                        err, err != PRO_TK_NO_ERROR );
    
    ProMenubuttonActionSet( (char*)"TkCLcmds", (char*)"-Recreate", 
	(ProMenubuttonAction)ProTestCustmzRecreate, (ProAppData)&opt ,
	TEST_NCLC_RECREATE	);
     
    ProMenubuttonActionSet( (char*)"TkCLcmds", (char*)"-Redefine", 
	(ProMenubuttonAction)ProTestCustmzRedefine, (ProAppData)&opt ,
	TEST_NCLC_REDEFINE);
     
    ProMenubuttonActionSet( (char*)"TkCLcmds", (char*)"-Create", 
	(ProMenubuttonAction)ProTestCustmzCreateMenuAct, (ProAppData)&opt ,
	TEST_NCLC_REDEFINE);
       
    ProMenubuttonActionSet( (char*)"TkCLcmds", (char*)"TkCLcmds", 
	(ProMenubuttonAction)ProMenuDelete, NULL , 0);
    ProMenubuttonActionSet( (char*)"TkCLcmds", (char*)"-Done", 
	    (ProMenubuttonAction)ProMenuDelete, NULL , 0);
     
    ProMenuCreate(PROMENUTYPE_MAIN, (char*)"TkCLcmds", NULL);
    ProMenuProcess((char*)"TkCLcmds", &menu_id);

    return 0;
}

/*====================================================================*\
FUNCTION : ProTestPrintErrs
PURPOSE  : print feature creation or redefinition errors
\*====================================================================*/
ProError ProTestPrintErrs1(
   ProErrorlist err_list)
{
    int i;
    char elem_name[PRO_LINE_SIZE];
    char elem_str[PRO_LINE_SIZE + 10];
    char err_str[50];
    char title[30];
    char text[100];

    for (i=0; i<err_list.error_number; i++)
    {
         if (ProUtilIdToStr(err_list.error_list->err_item_id, elem_name) ==
                                                    PRO_TK_E_NOT_FOUND)
            ProTKSprintf(elem_str, (char*)"Elem: %d", err_list.error_list->err_item_id);
         else
            ProTKSprintf(elem_str, (char*)"Elem: %s", elem_name);

         ProUtilErrPrint(err_list.error_list->error, err_str);

	 ProTKFprintf(stderr, (char*)"Err %d: %s, %s\n", i, err_str, elem_str);
         ProTKSprintf(title, (char*)"Error %d", i);
         ProTKSprintf(text, (char*)"%s, %s", err_str, elem_str);
	 ProTKPrintf ((char*)"%s\n", title);
	 ProTKPrintf ((char*)"%s\n",text);
	 
    }
    
    return (PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestSelectionPreCustFilter
PURPOSE  : 
\*====================================================================*/
ProError ProTestSelectionPreCustFilter(
    ProSelection selection,
    Pro3dPnt point,
    ProMatrix transform,
    char * option,
    int level,
    ProAppData app_data)
{
    ProModelitem feature;
    ProFeattype feat_type;
    ProError err;

    err = ProSelectionModelitemGet ( selection, &feature);
    TEST_CALL_REPORT("ProSelectionModelitemGet()",
			         "ProTestSelectionPreCustFilter()",
		     err, err != PRO_TK_NO_ERROR );

    err = ProFeatureTypeGet ( &feature, &feat_type);
    TEST_CALL_REPORT("ProFeatureTypeGet()",
			         "ProTestSelectionPreCustFilter()",
		     err, err != PRO_TK_NO_ERROR );
    if (feat_type == PRO_FEAT_CUSTOMIZE)

	return PRO_TK_NO_ERROR;


    return (PRO_TK_CONTINUE);

}

/*====================================================================*\
FUNCTION : ProTestSelectionPreNcseqFilter
PURPOSE  : 
\*====================================================================*/
ProError ProTestSelectionPreNcseqFilter(
    ProSelection selection,
    Pro3dPnt point,
    ProMatrix transform,
    char * option,
    int level,
    ProAppData app_data)
{
    ProModelitem feature;
    ProFeattype feat_type;
    ProError err;

    

    err = ProSelectionModelitemGet ( selection, &feature);
    TEST_CALL_REPORT("ProSelectionModelitemGet()",
			         "ProTestSelectionPreNcseqFilter()",
		     err, err != PRO_TK_NO_ERROR );

    err = ProFeatureTypeGet ( &feature, &feat_type);
    TEST_CALL_REPORT("ProFeatureTypeGet()",
			         "ProTestSelectionPreNcseqFilter()",
		     err, err != PRO_TK_NO_ERROR );
    if (feat_type == PRO_FEAT_AUXILIARY)

	return PRO_TK_NO_ERROR;


    return (PRO_TK_CONTINUE);

}

/*====================================================================*\
FUNCTION : ProTestCustmzSelect
PURPOSE  : Select cust. feature.
\*====================================================================*/
ProError ProTestCustmzSelect(
    ProSelection * customize )
{
    ProSelFunctions sel_funcs;
    ProError err;
    int nsels;
    ProSelection * sel;
    

    sel_funcs.pre_filter = (ProSelectionPreFilter)ProTestSelectionPreCustFilter;

    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, &nsels);
    TEST_CALL_REPORT("ProSelect()",
		     "ProTestCustmzSelect()",
		     err, err != PRO_TK_NO_ERROR );
    if (nsels == 0)
	*customize = NULL;
    else
	*customize = sel[0];
    
    return (err);
    
}

/*====================================================================*\
FUNCTION : ProTestNclActionDo
PURPOSE  :
\*====================================================================*/
ProError ProTestNclActionDo (
    ProElement elem_tree)
{
    ProError err;
    int menu_action, menu_id;
/*------------------------------------------------------------------------*\
 Select action for custm elem tree
\*------------------------------------------------------------------------*/
      err = ProMenuFileRegister( (char*)"TkClcmd", (char*)"tkclcmd.mnu", &menu_id );
        TEST_CALL_REPORT( "ProMenuFileRegister()", 
            "ProUtilNcseqElemSurfacesAdd()", 
	    err, err != PRO_TK_NO_ERROR );

        /* Define menu buttons */
        ProMenubuttonActionSet( (char*)"TkClcmd", (char*)"-Create",
            (ProMenubuttonAction)ProTestChooseNclAct, elem_tree,
				TEST_NCL_CREATE );
	
        ProMenubuttonActionSet( (char*)"TkClcmd", (char*)"-Remove",
            (ProMenubuttonAction)ProTestChooseNclAct, elem_tree,
				TEST_NCL_REMOVE);

	ProMenubuttonActionSet( (char*)"TkClcmd", (char*)"-RemoveByIdx",
            (ProMenubuttonAction)ProTestChooseNclAct, elem_tree,
				TEST_NCL_REMOVE_BY_IDX);
	
        ProMenubuttonActionSet( (char*)"TkClcmd", (char*)"-RedefineByIdx",
            (ProMenubuttonAction)ProTestChooseNclAct, elem_tree,
				TEST_NCL_REDEFINE_BY_IDX);

	ProMenubuttonActionSet( (char*)"TkClcmd", (char*)"-Redefine",
            (ProMenubuttonAction)ProTestChooseNclAct, elem_tree,
				TEST_NCL_REDEFINE);

	 ProMenubuttonActionSet( (char*)"TkClcmd", (char*)"-Done", 
            (ProMenubuttonAction)ProMenuDelete, NULL, 0 );
	
        ProMenubuttonActionSet( (char*)"TkClcmd", (char*)"TkClcmd", 
            (ProMenubuttonAction)ProMenuDelete, NULL, 0 );
	
	
        err = ProMenuCreate( PROMENUTYPE_MAIN, (char*)"TkClcmd", &menu_id );
        TEST_CALL_REPORT( "ProMenuCreate()", "ProTestNclActionDo()", 
			err, err != PRO_TK_NO_ERROR );
        if( err == PRO_TK_NO_ERROR )
        {
            err = ProMenuProcess( (char*)"TkClcmd", &menu_action );
            TEST_CALL_REPORT( "ProMenuProcess()", "ProTestNclActionDo()", 
	        err, err != PRO_TK_NO_ERROR );
        }
    return PRO_TK_NO_ERROR;
}


/*====================================================================*\
FUNCTION :ProTestCustmzCreate 
PURPOSE  : 
\*====================================================================*/
ProError ProTestCustmzCreate(
    int ref_ncseq_id, ProSelection owner)
{

   ProError         err = PRO_TK_NO_ERROR;
   ProElement       custmz_elem = NULL;
   ProElement       custmz_elem_tree = NULL;
   ProValue         value;
   ProValueData     value_data;
   ProErrorlist     errors;
   ProFeature       custmz_feat; 
   ProFeatureCreateOptions *opts = 0;
   static  UserElemTable custmz_elem_table[] = {
           { PRO_E_FEATURE_TYPE,      PRO_VALUE_TYPE_INT       },
           { PRO_E_REF_NCSEQ,         PRO_VALUE_TYPE_INT       },
           { PRO_E_NCL_COMMANDS,      ARRAY                    }};

   int     custmz_elem_type_size = sizeof (custmz_elem_table)/sizeof (UserElemTable);
   int ii;


   err = ProElementAlloc (PRO_E_FEATURE_TREE, &custmz_elem_tree);

   for (ii = 0; ii < custmz_elem_type_size; ii++)
   {
      err = ProElementAlloc (custmz_elem_table[ii].elem_type, &custmz_elem);
       TEST_CALL_REPORT( "ProElementAlloc()", "ProTestCustmzCreate()", 
			err, err != PRO_TK_NO_ERROR );

      switch (custmz_elem_table[ii].elem_type)
      {  
         case PRO_E_FEATURE_TYPE:
            err = ProElementIntegerSet (custmz_elem, PRO_FEAT_CUSTOMIZE);
            TEST_CALL_REPORT( "ProElementIntegerSet()", 
				  "ProTestCustmzCreate()", err, err != PRO_TK_NO_ERROR );
         break;
 
         case PRO_E_REF_NCSEQ:
			err = ProElementIntegerSet (custmz_elem, ref_ncseq_id);
            TEST_CALL_REPORT( "ProElementIntegerSet()", 
				  "ProTestCustmzCreate()", err, err != PRO_TK_NO_ERROR );
         break;
 
         case PRO_E_NCL_COMMANDS:
	      err = ProElemtreeElementAdd (custmz_elem_tree,
		  NULL, custmz_elem);
	      TEST_CALL_REPORT( "ProElemtreeElementAdd()",
		  "ProTestCustmzCreate()", 
			err, err != PRO_TK_NO_ERROR );
		 
	     err = ProTestNclActionDo (custmz_elem_tree);
		 
         break;

         default: 
            return PRO_TK_GENERAL_ERROR; 
      }     
 
      value_data.type = (ProValueDataType)custmz_elem_table[ii].val_type;
 
      if (custmz_elem_table[ii].val_type != ARRAY)
      {        
         if (err == PRO_TK_NO_ERROR)
         {
             err = ProElemtreeElementAdd (custmz_elem_tree, NULL, custmz_elem);
	     TEST_CALL_REPORT( "ProElemtreeElementAdd()",
		 "ProTestCustmzCreate()", 
			err, err != PRO_TK_NO_ERROR );
         }
         else
         {
             ProElementFree (&custmz_elem);
	     TEST_CALL_REPORT( "ProElementFree()", "ProTestCustmzCreate()", 
			err, err != PRO_TK_NO_ERROR );
         }
      }/* if ARRAY */

   }
   
 
   if (err == PRO_TK_NO_ERROR)
   {
      err = ProArrayAlloc(1,sizeof(ProFeatureCreateOptions),
            1, (ProArray*)&opts);

      opts[0]= PRO_FEAT_CR_NO_OPTS;

      err = ProFeatureWithoptionsCreate (owner, custmz_elem_tree,
            opts, PRO_REGEN_NO_FLAGS, &custmz_feat, &errors);
      TEST_CALL_REPORT( "ProFeatureWithoptionsCreate()", "ProTestCustmzCreate()", 
			err, err != PRO_TK_NO_ERROR );

      err = ProArrayFree((ProArray*)&opts);

   }

    if (err != PRO_TK_NO_ERROR)
     {
	 ProTestPrintErrs1(errors);
     }
   return err;
}

/*====================================================================*\
FUNCTION : 
PURPOSE  : 
\*====================================================================*/
int ProTestCustmzCreateMenuAct(
    void* p_dummy, 
    int action )
{
    ProError err;
    int nsels;
    ProSelection * sel;
    ProSelFunctions sel_funcs;
    int ref_ncseq_id;
    ProFeature ref_ncseq;
    ProSelection  custm_owner;
    ProMdl mfg;
    ProSolid       mfg_solid;
    ProAsmcomppath comp_path;
    ProModelitem   storage;
	
    sel_funcs.pre_filter = (ProSelectionPreFilter)ProTestSelectionPreNcseqFilter;

    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, &nsels);
    TEST_CALL_REPORT("ProSelect()",
		     "ProTestCustmzCreateMenuAct()",
		     err, err != PRO_TK_NO_ERROR );
    if (nsels <1)
	return PRO_TK_NO_ERROR;

    err = ProSelectionModelitemGet (sel[0], &ref_ncseq);
     TEST_CALL_REPORT("ProSelectionModelitemGet()",
		     "ProTestCustmzCreateMenuAct()",
		     err, err != PRO_TK_NO_ERROR );
    ref_ncseq_id = ref_ncseq.id; 

    err = ProMdlCurrentGet (&mfg);
    TEST_CALL_REPORT("ProMdlCurrentGet()",
		     "ProTestCustmzCreateMenuAct()",
		     err, err != PRO_TK_NO_ERROR );

    err = ProMfgSolidGet ((ProMfg)mfg, &mfg_solid);
     TEST_CALL_REPORT("ProMfgSolidGet()",
		     "ProTestCustmzCreateMenuAct()",
		     err, err != PRO_TK_NO_ERROR );

     err = ProMfgFeatureOwnerGet ((ProMfg)mfg, &comp_path);
     TEST_CALL_REPORT("ProMfgFeatureOwnerGet()",
		     "ProTestCustmzCreateMenuAct()",
		     err, err != PRO_TK_NO_ERROR );

     err = ProModelitemInit (mfg_solid, PRO_TK_NOT_USED,
			      (ProType)PRO_TK_NOT_USED, &storage );
     TEST_CALL_REPORT("ProModelitemInit()",
		     "ProTestCustmzCreateMenuAct()",
		     err, err != PRO_TK_NO_ERROR );
     err = ProSelectionAlloc (&comp_path, &storage,
			      &custm_owner);
     TEST_CALL_REPORT("ProSelectionAlloc()",
		     "ProTestCustmzCreateMenuAct()",
		     err, err != PRO_TK_NO_ERROR );

     err = ProTestCustmzCreate( ref_ncseq_id,  custm_owner);
     
     return (0);
     
    
}
/*====================================================================*\
FUNCTION : ProTestCustoElemtreeGet
PURPOSE  : 
\*====================================================================*/
ProError ProTestCustoElemtreeGet (
    ProModelitem* custm,
    ProSolid * mfg_solid,
    ProSelection * custm_owner,
    ProElement * elem_tree,
    ProAsmcomppath * comp_path )
{
    ProError err;
    ProSelection  customize;
    ProMdl mfg;
    ProModelitem   storage;
    ProMfgType m_type;
    
/*------------------------------------------------------------------------*\
  1. Select customize feature.
\*------------------------------------------------------------------------*/

    err = ProTestCustmzSelect (&customize);
    if (err != PRO_TK_NO_ERROR)
	return (PRO_TK_USER_ABORT);
        
    err = ProSelectionModelitemGet (customize, custm);
     TEST_CALL_REPORT("ProSelectionModelitemGet()",
        "ProTestCustoElemtreeGet()", err, err != PRO_TK_NO_ERROR );

/*------------------------------------------------------------------------*\
  2. Obtain ProSelection feature owner for ProFeatureCreate
     2a. Obtain manufacture storage solid
     2b. Obtain asm path to feature owner
     2c. Fill model item for storage solid
     2d. Create ProSelection for mfg feature owner
\*------------------------------------------------------------------------*/

    err = ProMdlCurrentGet (&mfg);
    TEST_CALL_REPORT("ProMdlCurrentGet()",
        "ProTestCustoElemtreeGet()", err, err != PRO_TK_NO_ERROR );

    err = ProMfgTypeGet ((ProMfg)mfg, &m_type);
    TEST_CALL_REPORT("ProMfgTypeGet()",
        "ProTestCustoElemtreeGet()", err, err != PRO_TK_NO_ERROR );
                     

    err = ProMfgSolidGet ((ProMfg)mfg, mfg_solid);
    TEST_CALL_REPORT("ProMfgSolidGet()",
        "ProTestCustoElemtreeGet()", err, err != PRO_TK_NO_ERROR );
        
    err = ProMfgFeatureOwnerGet ((ProMfg)mfg, comp_path);
    TEST_CALL_REPORT("ProMfgFeatureOwnerGet()", 
        "ProTestCustoElemtreeGet()", err, err != PRO_TK_NO_ERROR );

    err = ProModelitemInit ((*mfg_solid), PRO_TK_NOT_USED,
			      (ProType)PRO_TK_NOT_USED, &storage );
    TEST_CALL_REPORT("ProModelitemInit()", 
        "ProTestCustoElemtreeGet()", err, err != PRO_TK_NO_ERROR );

    err = ProSelectionAlloc (comp_path, &storage,
			      custm_owner);
    TEST_CALL_REPORT("ProSelectionAlloc()",
        "ProTestCustoElemtreeGet()", err, err != PRO_TK_NO_ERROR );
/*------------------------------------------------------------------------*\
  Naw we have ProSelection
  Next:
  Obtain elem tree 
\*------------------------------------------------------------------------*/

    err = ProFeatureElemtreeExtract (custm, NULL, PRO_FEAT_EXTRACT_NO_OPTS, elem_tree);
     TEST_CALL_REPORT("ProFeatureElemtreeExtract()",
        "ProTestCustoElemtreeGet()", err, err != PRO_TK_NO_ERROR );

     err = ProTestNclActionDo (*elem_tree);

     return err;
}

/*====================================================================*\
FUNCTION : ProTestCustmzRecreate
PURPOSE  : Select and recreate cust. feature.
\*====================================================================*/
int ProTestCustmzRecreate(
    void* p_dummy, 
    int action )
{
    ProError err;

    ProSelection  custm_owner;


    ProSolid       mfg_solid;
    ProAsmcomppath comp_path;
    ProModelitem    custm;



    ProElement elem_tree = NULL;
    ProFeature  new_custom;
    ProErrorlist  errors;
    ProFeatureCreateOptions *opts = 0;
    ProFeatureDeleteOptions *delete_opts = 0;
    int *feat_ids = NULL;

    err = ProTestCustoElemtreeGet (&custm, &mfg_solid, &custm_owner,
	&elem_tree, &comp_path);
    if (err == PRO_TK_USER_ABORT)
	return (0);
    

    err = ProArrayAlloc(1,sizeof(ProFeatureDeleteOptions),
        1, (ProArray*)&delete_opts);

    delete_opts[0] = PRO_FEAT_DELETE_NO_OPTS;

    err = ProArrayAlloc(1,sizeof(int),
        1, (ProArray*)&feat_ids);

    feat_ids[0] = custm.id;

     err = ProFeatureWithoptionsDelete (mfg_solid, feat_ids, 
     delete_opts, PRO_REGEN_NO_FLAGS);
     TEST_CALL_REPORT("ProFeatureWithoptionsDelete()",
		     "ProTestCustmzRecreate()",
		      err, err != PRO_TK_NO_ERROR );

     err = ProArrayFree((ProArray*)&delete_opts);
     err = ProArrayFree((ProArray*)&feat_ids);
     
/*------------------------------------------------------------------------*\
  Create feature

\*------------------------------------------------------------------------*/
	 
     err = ProArrayAlloc(1,sizeof(ProFeatureCreateOptions),
          1, (ProArray*)&opts);

     opts[0]= PRO_FEAT_CR_NO_OPTS;

     err = ProFeatureWithoptionsCreate (custm_owner, elem_tree,
          opts, PRO_REGEN_NO_FLAGS, &new_custom, &errors);
     TEST_CALL_REPORT("ProFeatureWithoptionsCreate()",
		     "ProTestCustmzRecreate()",
		      err, err != PRO_TK_NO_ERROR );

     err = ProArrayFree((ProArray*)&opts);
     if (err != PRO_TK_NO_ERROR)
     {
	 ProTestPrintErrs1(errors);
     }
     
		 
     return ( (int)err);
    
}

/*====================================================================*\
FUNCTION : ProTestCustmzRedefine
PURPOSE  : Select and redefine cust. feature.
\*====================================================================*/
int ProTestCustmzRedefine(
    void* p_dummy, 
    int action )
{
    ProError err;


    ProSelection  custm_owner;


    ProSolid       mfg_solid;
    ProAsmcomppath comp_path;

    ProModelitem custm;

    ProElement elem_tree = NULL;
    ProErrorlist  errors;
    ProFeatureCreateOptions *opts = 0;


    err = ProTestCustoElemtreeGet (&custm, &mfg_solid, &custm_owner,
	&elem_tree, &comp_path);
    if (err == PRO_TK_USER_ABORT)
	return (0);

/*------------------------------------------------------------------------*\
  Redefine feature

\*------------------------------------------------------------------------*/
     err = ProArrayAlloc(1,sizeof(ProFeatureCreateOptions),
          1, (ProArray*)&opts);

     opts[0]= PRO_FEAT_CR_NO_OPTS;

     err = ProFeatureWithoptionsRedefine (&comp_path, &custm, elem_tree ,
          opts, PRO_REGEN_NO_FLAGS, &errors);
     TEST_CALL_REPORT("ProFeatureWithoptionsRedefine()",
		     "ProTestCustmzRedefine()",
		      err, err != PRO_TK_NO_ERROR );

     err = ProArrayFree((ProArray*)&opts);
     if (err != PRO_TK_NO_ERROR)
     {
	 ProTestPrintErrs1(errors);
     }
     
	 
    
    return (0);
    
}


/*====================================================================*\
FUNCTION : TestFileGet
PURPOSE  : 
\*====================================================================*/
int TestFileGet ( FILE ** ff)
{
    ProCharLine ch_file_name;
    ProLine wname;
    
    do
    {
	ProUtilMsgPrint((char*)"gen",(char*)"TEST %0s",
			"Enter file name [NONE]: ");
	if (!ProUtilStringGet(wname, NULL, PRO_LINE_SIZE-1))
	    return (1);
	ProWstringToString (ch_file_name, wname);
	
    }while ((*ff = PTApplsUnicodeFopen (ch_file_name, "rt")) == NULL);
    
    return 0;
}


/*====================================================================*\
FUNCTION : ProTestClCmdDataGet
PURPOSE  : 
\*====================================================================*/
int ProTestClCmdDataGet (
    FILE *cmgfile,            /* in */
    wchar_t*** cmds,             /*  out wlines */
    int  *   icmds,
    ProVector  cmd_loc,       /* out */
    ProVector  cmd_axis)      /* out */
{
    ProCharLine cstr_from;
    char * cur_tk;
    char * end_dbl;
    double dbl, * pdbl;
    wchar_t * wcur_tk;
    int i;
    ProError err;
    
    memset (cmd_loc, 0, sizeof (ProVector));
    memset (cmd_axis, 0, sizeof (ProVector));

    err = ProArrayAlloc (0, sizeof (wchar_t*), 1, (ProArray *)cmds );
    TEST_CALL_REPORT("ProArrayAlloc()",
			         "ProTestClCmdDataGet()",
				  err, err != PRO_TK_NO_ERROR );
    
    if ( (fgets (cstr_from, PRO_LINE_SIZE, cmgfile ) == NULL)
	|| (cstr_from[0] == '\0') || (cstr_from[0] == '\n'))
	return 0;

    cur_tk = strtok ((char*)cstr_from, " \t,\n");
    dbl = strtod ( cur_tk, &end_dbl);
    if (cur_tk == end_dbl && cur_tk != NULL)
    {
	wcur_tk = (wchar_t *) calloc (PRO_LINE_SIZE, sizeof (wchar_t));
	
	ProStringToWstring (wcur_tk, cur_tk);
	err = ProArrayObjectAdd ((ProArray*) cmds, PRO_VALUE_UNUSED,1,
				 &wcur_tk);
    }
    else
	return (0);
    
    for (i = 0;
	 (cur_tk = strtok (NULL, " \t,\n")) != NULL;
	 i++)
    {
	dbl = strtod ( cur_tk, &end_dbl);
	
	if (cur_tk == end_dbl)
	{
	    
	    wcur_tk = (wchar_t *) calloc(PRO_LINE_SIZE, sizeof (wchar_t));
	    
	    ProStringToWstring (wcur_tk, cur_tk);
	    
	    err = ProArrayObjectAdd ((ProArray*) cmds, PRO_VALUE_UNUSED,
				     1, &wcur_tk);
	    
	    TEST_CALL_REPORT("ProArrayObjectAdd()",
			         "ProTestClCmdDataGet()",
				  err, err != PRO_TK_NO_ERROR );
	    i--;
	    continue;
	}

	pdbl = ((i<3) ? &(cmd_loc[i]) : &(cmd_axis[i-3]));
	*pdbl = dbl;
    }

    err = ProArraySizeGet ((ProArray)*cmds, icmds);
    TEST_CALL_REPORT("ProArraySizeGet()",
			         "ProTestClCmdDataGet()",
				  err, err != PRO_TK_NO_ERROR );

    wcur_tk = NULL;
    err = ProArrayObjectAdd ((ProArray*) cmds, PRO_VALUE_UNUSED,1, &wcur_tk);
    TEST_CALL_REPORT("ProArrayObjectAdd()",
			         "ProTestClCmdDataGet()",
				  err, err != PRO_TK_NO_ERROR );    
    return (1);
}


/*====================================================================*\
FUNCTION : ProTestClCmdDataPrint
PURPOSE  : 
\*====================================================================*/
int ProTestClCmdDataPrint (
    wchar_t** cmds,             /*  out wlines */
    int  icmds,
    ProVector  cmd_loc,       /* out */
    ProVector  cmd_axis)      /* out */
{
    int arr_size, i;
    ProError err;
    ProCharLine cstr;

    err = ProArraySizeGet ((ProArray) cmds, &arr_size);
    TEST_CALL_REPORT("ProArraySizeGet()",
			         "ProTestClCmdDataPrint()",
				  err, err != PRO_TK_NO_ERROR );
    
    for (i= 0; i<arr_size; i++)
    {
	if (cmds[i] != NULL)
	{
	    ProWstringToString (cstr, cmds[i]);
	    ProTKPrintf ((char*)"%s ", cstr);
	}	
    }

    ProTKPrintf ((char*)"%d ", icmds);
 
    ProTKPrintf ((char*)"%f %f %f %f %f %f \n", cmd_loc[0],  cmd_loc[1],    cmd_loc[2],
	    cmd_axis[0],  cmd_axis[1],    cmd_axis[2]);

    return 0;
}


/*====================================================================*\
FUNCTION : ProTestClcmdElemCreate
PURPOSE  : reads info  from file creats Clcmd elements and adds
\*====================================================================*/
ProError ProTestClcmdElemCreate(
    ProElement NclCmds)       /* elem to add Clcmds elements */
{
#ifndef PT_PRODUCTS_BUILD
    ProError err;
    
    FILE * clcs_file;
    wchar_t **wlines;
    int incmds;

    ProElement ncl_commd_elem;
    double * pos;
    double *axis;

    ProVector commd_loc, commd_axis;
    if ( TestFileGet ( &clcs_file) )
	return (PRO_TK_GENERAL_ERROR);


    for (;ProTestClCmdDataGet(clcs_file, &wlines, &incmds,
			      commd_loc, commd_axis);)
    {
	ProTestClCmdDataPrint( wlines, incmds, commd_loc, commd_axis);

	 if (commd_loc[0] == 0.0 && commd_loc[1] == 0.0
	     && commd_loc[2] == 0.0)
	     pos = NULL;
	 else
	     pos = commd_loc;
	 
	 if (commd_axis[0] == 0.0 && commd_axis[1] == 0.0
	     && commd_axis[2] == 0.0)
	     axis = NULL;
	 else
	     axis = commd_axis;
	    
	     
	 err = ProClcmdElemCreate ((wchar_t**)wlines, incmds, pos,
				   axis, &ncl_commd_elem);
	 TEST_CALL_REPORT("ProClcmdElemCreate()",
			         "ProTestClcmdElemCreate()",
				  err, err != PRO_TK_NO_ERROR );
	     
	 
	     
	  err = ProClcmdElemAdd (NclCmds, ncl_commd_elem, -1);
	  TEST_CALL_REPORT("ProClcmdElemAdd()",
			         "ProTestClcmdElemCreate()",
				  err, err != PRO_TK_NO_ERROR );
	    
	err =ProTestCmdsArrayFree (&wlines);
    }


    fclose (clcs_file);
    
    return (PRO_TK_NO_ERROR);
#else
    return PRO_TK_NOT_IMPLEMENTED;
#endif
}

    
/*====================================================================*\
FUNCTION : ProTestClcmdRemove
PURPOSE  : reads info  from file and removes Clcmd elements 
\*====================================================================*/
ProError ProTestClcmdElemRemove(
    ProElement elem_tree)       /* elem tree */
{
 #ifndef PT_PRODUCTS_BUILD
    ProError err;
    FILE * clcs_file;
    wchar_t * *wlines;
    int incmds;
    double * pos;
    double *axis;

    ProVector commd_loc, commd_axis;
    if ( TestFileGet ( &clcs_file) )
	return (PRO_TK_GENERAL_ERROR);

    for (;ProTestClCmdDataGet(clcs_file, &wlines, &incmds,
			      commd_loc, commd_axis);)
    {

	ProTestClCmdDataPrint( wlines, incmds, commd_loc, commd_axis);

	 if (commd_loc[0] == 0.0 && commd_loc[1] == 0.0
	     && commd_loc[2] == 0.0)
	     pos = NULL;
	 else
	     pos = commd_loc;
	 
	 if (commd_axis[0] == 0.0 && commd_axis[1] == 0.0
	     && commd_axis[2] == 0.0)
	     axis = NULL;
	 else
	     axis = commd_axis;
	     
	 
	 err = ProClcmdElemRemove (elem_tree, wlines, incmds, pos, axis, NULL);
	 TEST_CALL_REPORT("ProClcmdElemRemove()",
			         "ProTestClcmdElemRemove()",
				  err, err != PRO_TK_NO_ERROR );
	     
	 ProTestCmdsArrayFree (&wlines);

    }

    fclose (clcs_file);
    
    
    return (PRO_TK_NO_ERROR);
#else
    return PRO_TK_NOT_IMPLEMENTED;
#endif
}


/*====================================================================*\
FUNCTION : ProTestClcmdRemoveByIndex
PURPOSE  : ask indexes and removes Clcmd elements 
\*====================================================================*/
ProError ProTestClcmdElemRemoveByIndex(
    ProElement elem_tree)       /* elem tree */
{
#ifndef PT_PRODUCTS_BUILD 
    ProError err;
    int index, range[2] = {0, 100};

    while (1 == 1)
    {
	ProUtilMsgPrint((char*)"gen",(char*)"TEST %0s",
			"Enter an element index to remove [Quit]: ");
	if (!ProUtilIntGet(range, NULL, &index))
	    return (PRO_TK_NO_ERROR);
	
	err = ProClcmdElemRemoveByIndex (elem_tree, index, NULL);
	 TEST_CALL_REPORT("ProClcmdElemRemoveByIndex()",
			         "ProTestClcmdElemRemoveByIndex()",
				  err, err != PRO_TK_NO_ERROR );	    
    }

#else
    return PRO_TK_NOT_IMPLEMENTED;
#endif
}

 
/*====================================================================*\
FUNCTION : ProTestClcmdAdd
PURPOSE  : Adds custamazed elem to feature tree 
\*====================================================================*/
ProError ProTestClcmdElemAdd(
    ProElement elem_tree)       /* elem tree */
{

    return (PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION : ProTestClcmdRedefineByIndex
PURPOSE  : ask indexes and reads info  from file to redefine Clcmd elements 
\*====================================================================*/
ProError ProTestClcmdElemRedefineByIndex(
    ProElement elem_tree)       /* elem tree */
{
#ifndef PT_PRODUCTS_BUILD
    ProError err;
    FILE * clcs_file;
    wchar_t *  *wlines;
    ProElement ncl_commd_elem;
    double * pos;
    double *axis;
    int index, range[2] = {0, 100};
    int incmds;
    ProVector commd_loc, commd_axis;


   if ( TestFileGet ( &clcs_file) )
	return (PRO_TK_GENERAL_ERROR);

   while (1 == 1)
    {
	ProUtilMsgPrint((char*)"gen",(char*)"TEST %0s",
			"Enter an element index to redefine [Quit]: ");
	if (!ProUtilIntGet(range, NULL, &index))
	    break;

	
	err = ProClcmdElemGetByIndex (elem_tree, index, &ncl_commd_elem);
	TEST_CALL_REPORT("ProClcmdElemGetByIndex()",
			         "ProTestClcmdElemRedefineByIndex()",
				  err, err != PRO_TK_NO_ERROR );

	    
	 if (!ProTestClCmdDataGet(clcs_file, &wlines, &incmds,
			      commd_loc, commd_axis))
	     break;
	 ProTestClCmdDataPrint( wlines, incmds, commd_loc, commd_axis);
	 
	 if (commd_loc[0] == 0.0 && commd_loc[1] == 0.0
	     && commd_loc[2] == 0.0)
	     pos = NULL;
	 else
	     pos = commd_loc;
	 
	 if (commd_axis[0] == 0.0 && commd_axis[1] == 0.0
	     && commd_axis[2] == 0.0)
	     axis = NULL;
	 else
	     axis = commd_axis;

	 
	     
	 err = ProClcmdElemSet (ncl_commd_elem, wlines, incmds, pos, axis);
	 TEST_CALL_REPORT("ProClcmdElemSet()",
			         "ProTestClcmdElemRedefineByIndex()",
				  err, err != PRO_TK_NO_ERROR );
	     
	 ProTestCmdsArrayFree (&wlines);
	
    }
   
    fclose (clcs_file);

    return (PRO_TK_NO_ERROR);
#else
    return PRO_TK_NOT_IMPLEMENTED;
#endif
}
/*====================================================================*\
FUNCTION : ProTestClcmdRedefine
PURPOSE  : reads info  from one file to redefine Clcmd elements
using info from anather file
\*====================================================================*/
ProError ProTestClcmdElemRedefine(
    ProElement elem_tree)       /* elem tree */
{
#ifndef PT_PRODUCTS_BUILD
    ProError err;
    FILE * clcs_file_from;
    FILE * clcs_file_to;
    wchar_t * *wlines;
    wchar_t * *wlines_to;
    int incmds;

    ProElement ncl_commd_elem;
    double * pos;
    double *axis;
    
    ProVector commd_loc, commd_axis;

    
    if ( TestFileGet ( &clcs_file_from) )
	return (PRO_TK_GENERAL_ERROR);
    if ( TestFileGet ( &clcs_file_to) )
    {
	fclose (clcs_file_from);
	return (PRO_TK_GENERAL_ERROR);
    }
    
  
    for (;ProTestClCmdDataGet(clcs_file_from, &wlines, &incmds,
			      commd_loc, commd_axis);)
    {

	ProTestClCmdDataPrint( wlines, incmds, commd_loc, commd_axis);
	

	 if (commd_loc[0] == 0.0 && commd_loc[1] == 0.0
	     && commd_loc[2] == 0.0)
	     pos = NULL;
	 else
	     pos = commd_loc;
	 
	 if (commd_axis[0] == 0.0 && commd_axis[1] == 0.0
	     && commd_axis[2] == 0.0)
	     axis = NULL;
	 else
	     axis = commd_axis;

	     
	 err = ProClcmdElemGet (elem_tree, wlines, incmds,  pos, axis,
				&ncl_commd_elem);
	     

				
	 TEST_CALL_REPORT("ProClcmdElemGet()",
			         "ProTestClcmdElemRedefine()",
				  err, err != PRO_TK_NO_ERROR );

	 if (!ProTestClCmdDataGet(clcs_file_to, &wlines_to, &incmds,
			      commd_loc, commd_axis))
	     break;
	 ProTestClCmdDataPrint( wlines_to, incmds, commd_loc, commd_axis);


	 if (commd_loc[0] == 0.0 && commd_loc[1] == 0.0
	     && commd_loc[2] == 0.0)
	     pos = NULL;
	 else
	     pos = commd_loc;
	 
	 if (commd_axis[0] == 0.0 && commd_axis[1] == 0.0
	     && commd_axis[2] == 0.0)
	     axis = NULL;
	 else
	     axis = commd_axis;

	     
	 err = ProClcmdElemSet (ncl_commd_elem, wlines_to, incmds, pos, axis);
	 
	 TEST_CALL_REPORT("ProClcmdElemSet()",
			         "ProTestClcmdElemRedefine()",
				  err, err != PRO_TK_NO_ERROR );
	     
	  ProTestCmdsArrayFree (&wlines);
	  ProTestCmdsArrayFree (&wlines_to);
    }
	 

    fclose (clcs_file_from);
    fclose (clcs_file_to);
   
    return (PRO_TK_NO_ERROR);
#else
    return PRO_TK_NOT_IMPLEMENTED;
#endif
}

/*====================================================================*\
FUNCTION : ProTestCmdsArrayFree
PURPOSE  : 
\*====================================================================*/
ProError ProTestCmdsArrayFree (
    wchar_t*** cmds)             /*  in wlines */
{
    int arr_size, i;
    ProError err;
    

    err = ProArraySizeGet ((ProArray) *cmds, &arr_size);
    TEST_CALL_REPORT("ProArraySizeGet()",
			         "ProTestCmdsArrayFree()",
				  err, err != PRO_TK_NO_ERROR );
	
    for (i= 0; i<arr_size; i++)
    {
	
	if ((*cmds)[i] != NULL)
	    free ((*cmds)[i]);
    }
	

    err = ProArrayFree ((ProArray *) cmds );
    TEST_CALL_REPORT("ProArrayFree()",
			         "ProTestCmdsArrayFree()",
		     err, err != PRO_TK_NO_ERROR );
    return err;
}