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


#include <ProToolkitErrors.h>
#include <ProSelection.h>
#include <ProElement.h>
#include <ProMfg.h>
#include <ProMfgOptions.h>
#include <ProUtil.h>
#include <ProTKRunTime.h>
#include <ProCrvcollection.h>

#include <TestError.h>
#include <UtilString.h>
#include <TestConsts.h>
#include <UgMfg.h>


/*====================================================================*\
FUNCTION : UserToolMtnOffsetSet
PURPOSE  : Set "Tool motion offset" element
\*====================================================================*/
ProError UserToolMtnOffsetSet( 
/*--------------------------------------------------------------------*/
double		x_offset,
double		y_offset,
double		z_offset,
ProElement	offset_elem

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProElement		element;
 ProValueData		value_data;
 ProValue		value;
 int			ii = 0, table_size = 0;
 static ElemTable	elem_table[] = 
 {
   { PRO_E_TOOL_MTN_X_OFFSET, PRO_VALUE_TYPE_DOUBLE },
   { PRO_E_TOOL_MTN_X_OFFSET, PRO_VALUE_TYPE_DOUBLE },
   { PRO_E_TOOL_MTN_Z_OFFSET, PRO_VALUE_TYPE_DOUBLE }
 };

 table_size = sizeof( elem_table ) / sizeof( ElemTable );

 for ( ii = 0; ii < table_size; ii++ )
 {
   err = ProElementAlloc( elem_table[ii].elem_type, &element );
   ERROR_CHECK( "UserToolMtnOffsetSet","ProElementAlloc()", err );

   switch ( elem_table[ii].elem_type )
   {
     case PRO_E_TOOL_MTN_X_OFFSET:
		err = ProElementDoubleSet ( element, x_offset);
		ERROR_CHECK( "UserToolMtnOffsetSet", "ProElementDoubleSet", err );
        break;

     case PRO_E_TOOL_MTN_Y_OFFSET:
		err = ProElementDoubleSet ( element, y_offset);
		ERROR_CHECK( "UserToolMtnOffsetSet", "ProElementDoubleSet", err );
        break;

     case PRO_E_TOOL_MTN_Z_OFFSET:
		err = ProElementDoubleSet ( element, z_offset);
		ERROR_CHECK( "UserToolMtnOffsetSet", "ProElementDoubleSet", err );
        break;

     default:
        ProTKFprintf( stderr, "Error setting element type\n" );
        err = PRO_TK_GENERAL_ERROR;
        ERROR_CHECK( "UserToolMtnOffsetSet", "UserToolMtnOffsetSet()", err );
        break;
   }
   err = ProElemtreeElementAdd( offset_elem, NULL, element );
   ERROR_CHECK( "UserToolMtnOffsetSet", "ProElemtreeElementAdd", err );
 }

 return ( err );
}

/*====================================================================*\
FUNCTION : UserToolMtnPlungeSet
PURPOSE  : Set "Plunge" tool motion
\*====================================================================*/
ProError UserToolMtnPlungeSet( 
/*--------------------------------------------------------------------*/
MfgPrmDblValue  dbl_params[],
int		n_dbl_params,
MfgPrmStrValue  str_params[],
int		n_str_params,
double		x_offset,
double		y_offset,
double		z_offset,
ProSelection	axis,
ProElement	tool_mtn_elem

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProElement		element;
 ProValueData		value_data;
 ProValue		value;
 ProSelection		selection;
 ProReference		reference;
 int			ii = 0, table_size = 0;
 static ElemTable	elem_table[] = 
 {
   { PRO_E_TOOL_MTN_TYPE,     PRO_VALUE_TYPE_INT       },
   { PRO_E_MFG_PARAM_ARR,     ARRAY                    },
   { PRO_E_TOOL_MTN_OFFSET,   COMPOUND                 },
   { PRO_E_TOOL_MTN_AXIS_REF, PRO_VALUE_TYPE_SELECTION }
 };

 table_size = sizeof( elem_table ) / sizeof( ElemTable );

 for ( ii = 0; ii < table_size; ii++ )
 {
   err = ProElementAlloc( elem_table[ii].elem_type, &element );
   ERROR_CHECK( "UserToolMtnPlungeSet","ProElementAlloc()", err );

   switch ( elem_table[ii].elem_type )
   {
     case PRO_E_TOOL_MTN_TYPE:
      break;

     case PRO_E_MFG_PARAM_ARR:
      err = UserMfgParamArrSet( dbl_params, n_dbl_params,
                                str_params, n_str_params,
                                element );
      ERROR_CHECK( "UserToolMtnPlungeSet", "UserMfgParamArrSet()", err );
      break;

     case PRO_E_TOOL_MTN_OFFSET:
        err = UserToolMtnOffsetSet( x_offset, y_offset, z_offset,
                                    element );
        ERROR_CHECK( "UserToolMtnPlungeSet", "UserToolMtnOffsetSet()", err );
        break;

     case PRO_E_TOOL_MTN_AXIS_REF:
        if ( axis == NULL )
        {
          err = ProElementFree( &element );
          continue;
        }
        else
          selection = axis;
        break;

     default:
        ProTKFprintf( stderr, "Error setting element type\n" );
        err = PRO_TK_GENERAL_ERROR;
        ERROR_CHECK( "UserToolMtnPlungeSet", "UserToolMtnPlungeSet()", err );
        break;
   }

   if ( elem_table[ii].val_type == PRO_VALUE_TYPE_INT )
   {

  

     err = ProElementIntegerSet(element,PRO_TM_TYPE_PLUNGE);
     ERROR_CHECK( "UserToolMtnPlungeSet", "ProElementIntegerSet()", err );
   }
   else if ( elem_table[ii].val_type == PRO_VALUE_TYPE_SELECTION )
   {
     err = ProSelectionToReference( selection, &reference );
     ERROR_CHECK( "UserToolMtnPlungeSet()", "ProSelectionToReference", err );

     err = ProElementReferenceSet( element, reference );
     ERROR_CHECK( "UserToolMtnPlungeSet()", "ProElementReferenceSet", err );
   }

   err = ProElemtreeElementAdd( tool_mtn_elem, NULL, element );
   ERROR_CHECK( "UserToolMtnPlungeSet", "ProElemtreeElementAdd", err );
 }

 return ( err );
}

/*====================================================================*\
FUNCTION : UserToolMtnLeadSet
PURPOSE  : Set "Lead In" tool motion element
\*====================================================================*/
ProError UserToolMtnLeadSet( 
/*--------------------------------------------------------------------*/
ProTmType	lead_tm_type,
MfgPrmDblValue  dbl_params[],
int		n_dbl_params,
MfgPrmStrValue  str_params[],
int		n_str_params,
ProTmSideDir	dir_opt,
ProSelection	axis,
ProElement	tool_mtn_elem

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProElement		element;
 ProValueData		value_data;
 ProValue		value;
 ProSelection		selection;
 ProReference		reference;
 int			ii = 0, table_size = 0;
 static ElemTable	elem_table[] = 
 {
   { PRO_E_TOOL_MTN_TYPE,     PRO_VALUE_TYPE_INT       },
   { PRO_E_MFG_PARAM_ARR,     ARRAY                    },
   { PRO_E_MFG_APPR_EXIT_DIR, PRO_VALUE_TYPE_INT       },
   { PRO_E_TOOL_MTN_AXIS_REF, PRO_VALUE_TYPE_SELECTION }
 };

 table_size = sizeof( elem_table ) / sizeof( ElemTable );

 for ( ii = 0; ii < table_size; ii++ )
 {
   err = ProElementAlloc( elem_table[ii].elem_type, &element );
   ERROR_CHECK( "UserToolMtnLeadSet","ProElementAlloc()", err );

   switch ( elem_table[ii].elem_type )
   {
     case PRO_E_TOOL_MTN_TYPE:
		err = ProElementIntegerSet ( element, lead_tm_type);
		ERROR_CHECK( "UserToolMtnLeadSet", "ProElementIntegerSet()", err);
        break;

     case PRO_E_MFG_PARAM_ARR:
        err = UserMfgParamArrSet( dbl_params, n_dbl_params,
                                  str_params, n_str_params,
                                  element );
        ERROR_CHECK( "UserToolMtnLeadSet", "UserMfgParamArrSet()", err );
        break;

     case PRO_E_MFG_APPR_EXIT_DIR:
		err = ProElementIntegerSet ( element, dir_opt);
		ERROR_CHECK( "UserToolMtnLeadSet", "ProElementIntegerSet()", err);
        break;

     case PRO_E_TOOL_MTN_AXIS_REF:
        if ( axis == NULL )
        {
          err = ProElementFree( &element );
          continue;
        }
        else
          selection = axis;
        break;

     default:
        ProTKFprintf( stderr, "Error setting element type\n" );
        err = PRO_TK_GENERAL_ERROR;
        break;
   }


   if ( elem_table[ii].val_type == PRO_VALUE_TYPE_SELECTION )
   {
     err = ProSelectionToReference( selection, &reference );
     ERROR_CHECK( "UserToolMtnLeadSet()", "ProSelectionToReference", err );

     err = ProElementReferenceSet( element, reference );
     ERROR_CHECK( "UserToolMtnLeadSet()", "ProElementReferenceSet", err );
   }

   err = ProElemtreeElementAdd( tool_mtn_elem, NULL, element );
   ERROR_CHECK( "UserToolMtnLeadSet", "ProElemtreeElementAdd", err );
 }

 return ( err );
}

/*====================================================================*\
FUNCTION : UserToolMtnLeadInSet
PURPOSE  : Set "Lead In" tool motion element
\*====================================================================*/
ProError UserToolMtnLeadInSet(
/*--------------------------------------------------------------------*/
MfgPrmDblValue  dbl_params[],
int             n_dbl_params,
MfgPrmStrValue  str_params[],
int             n_str_params,
ProTmSideDir    dir_opt,
ProSelection    axis,
ProElement      tool_mtn_elem

)
/*--------------------------------------------------------------------*/
{
 ProError	err = PRO_TK_NO_ERROR; 

 err = UserToolMtnLeadSet( PRO_TM_TYPE_LEAD_IN,
                           dbl_params, 
                           n_dbl_params, 
                           str_params,
                           n_str_params,
                           dir_opt,
                           axis,
                           tool_mtn_elem );
 return ( err );
}

/*====================================================================*\
FUNCTION : UserToolMtnLeadOutSet
PURPOSE  : Set "Lead Out" tool motion element
\*====================================================================*/
ProError UserToolMtnLeadOutSet(
/*--------------------------------------------------------------------*/
MfgPrmDblValue  dbl_params[],
int             n_dbl_params,
MfgPrmStrValue  str_params[],
int             n_str_params,
ProTmSideDir    dir_opt,
ProSelection    axis,
ProElement      tool_mtn_elem

)
/*--------------------------------------------------------------------*/
{
 ProError	err = PRO_TK_NO_ERROR; 

 err = UserToolMtnLeadSet( PRO_TM_TYPE_LEAD_OUT,
                           dbl_params, 
                           n_dbl_params, 
                           str_params,
                           n_str_params,
                           dir_opt,
                           axis,
                           tool_mtn_elem );
 return ( err );
}

/*====================================================================*\
FUNCTION : UserToolMtnRetractSet
PURPOSE  : Set "Retract" tool motion element
\*====================================================================*/
ProError UserToolMtnRetractSet( 
/*--------------------------------------------------------------------*/
MfgPrmDblValue  dbl_params[],
int		n_dbl_params,
MfgPrmStrValue  str_params[],
int		n_str_params,
ProElement	tool_mtn_elem

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProElement		element;
 ProValueData		value_data;
 ProValue		value;
 ProSelection		selection;
 ProReference		reference;
 int			ii = 0, table_size = 0;
 static ElemTable	elem_table[] = 
 {
   { PRO_E_TOOL_MTN_TYPE,     PRO_VALUE_TYPE_INT       },
   { PRO_E_MFG_PARAM_ARR,     ARRAY                    }
 };

 table_size = sizeof( elem_table ) / sizeof( ElemTable );

 for ( ii = 0; ii < table_size; ii++ )
 {
   err = ProElementAlloc( elem_table[ii].elem_type, &element );
   ERROR_CHECK( "UserToolMtnRetractSet","ProElementAlloc()", err );

   switch ( elem_table[ii].elem_type )
   {
     case PRO_E_TOOL_MTN_TYPE:
        break;

     case PRO_E_MFG_PARAM_ARR:
        err = UserMfgParamArrSet( dbl_params, n_dbl_params,
                                  str_params, n_str_params,
                                  element );
        ERROR_CHECK( "UserToolMtnRetractSet", "UserMfgParamArrSet()", err );
        break;

     default:
        ProTKFprintf( stderr, "Error setting element type\n" );
        err = PRO_TK_GENERAL_ERROR;
        ERROR_CHECK( "UserToolMtnRetractSet", "UserToolMtnRetractSet()", 
                     err );
        break;
   }

   if ( elem_table[ii].val_type == PRO_VALUE_TYPE_INT )
   {

  

     err = ProElementIntegerSet(element,PRO_TM_TYPE_GO_RETRACT);
     ERROR_CHECK( "UserToolMtnRetractSet", "ProElementIntegerSet()", err );
   }

   err = ProElemtreeElementAdd( tool_mtn_elem, NULL, element );
   ERROR_CHECK( "UserToolMtnRetractSet", "ProElemtreeElementAdd", err );
 }

 return ( err );
}

/*====================================================================*\
FUNCTION : UserSimpleClCommandSet
PURPOSE  : Set "CL command" element without datum point or surface 
           selection.
\*====================================================================*/
ProError UserSimpleClCommandSet( 
/*--------------------------------------------------------------------*/
wchar_t		*cl_command_wstr,
ProClCmdLocType	location_type,
double		location_param,
ProElement	tool_mtn_elem

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProElement		element;
 ProValueData		value_data;
 ProValue		value;
 int			ii = 0, table_size = 0;
 static ElemTable	elem_table[] = 
 {
   { PRO_E_TOOL_MTN_CL_CMD_LOC_TYPE,     PRO_VALUE_TYPE_INT       },
   { PRO_E_TOOL_MTN_CL_CMD_STR,          PRO_VALUE_TYPE_WSTRING   },
   { PRO_E_TOOL_MTN_CL_CMD_PARAM,        PRO_VALUE_TYPE_DOUBLE    },
 };

 table_size = sizeof( elem_table ) / sizeof( ElemTable );

 for ( ii = 0; ii < table_size; ii++ )
 {
   err = ProElementAlloc( elem_table[ii].elem_type, &element );
   ERROR_CHECK( "UserSimpleClCommandSet","ProElementAlloc()", err );

   switch ( elem_table[ii].elem_type )
   {
     case PRO_E_TOOL_MTN_CL_CMD_LOC_TYPE:
		err = ProElementIntegerSet ( element, location_type);
		ERROR_CHECK( "UserSimpleClCommandSet", "ProElementIntegerSet()", err);
        break;

     case PRO_E_TOOL_MTN_CL_CMD_STR:
		err = ProElementWstringSet( element, cl_command_wstr);
		ERROR_CHECK( "UserSimpleClCommandSet", "ProElementWstringSet()", err);
        break;

     case PRO_E_TOOL_MTN_CL_CMD_PARAM:
		err = ProElementDoubleSet ( element, location_param);
		ERROR_CHECK( "UserSimpleClCommandSet", "ProElementDoubleSet()", err);
        break;

     default:
        ProTKFprintf( stderr, "Error setting element type\n" );
        err = PRO_TK_GENERAL_ERROR;
        ERROR_CHECK( "UserSimpleClCommandSet", "UserSimpleClCommandSet()", 
                     err );
        break;
   }

   err = ProElemtreeElementAdd( tool_mtn_elem, NULL, element );
   ERROR_CHECK( "UserSimpleClCommandSet", "ProElemtreeElementAdd", err );
 }

 return ( err );
}

/*====================================================================*\
FUNCTION : UserToolMtnSimpleClCommandSet
PURPOSE  : Set "CL command" tool motion element
           In this example - simple cl command specification without 
           referencing datum point or surface.
\*====================================================================*/
ProError UserToolMtnSimpleClCommandSet( 
/*--------------------------------------------------------------------*/
wchar_t		*cl_command_wstr,
ProClCmdLocType	location_type,
double		param,
ProElement	tool_mtn_elem

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProElement		element;
 ProValueData		value_data;
 ProValue		value;
 int			ii = 0, table_size = 0;
 static ElemTable	elem_table[] = 
 {
   { PRO_E_TOOL_MTN_TYPE,       PRO_VALUE_TYPE_INT },
   { PRO_E_TOOL_MTN_CL_CMD,     COMPOUND           }
 };

 table_size = sizeof( elem_table ) / sizeof( ElemTable );

 for ( ii = 0; ii < table_size; ii++ )
 {
   err = ProElementAlloc( elem_table[ii].elem_type, &element );
   ERROR_CHECK( "UserToolMtnSimpleClCommandSet","ProElementAlloc()", err );

   switch ( elem_table[ii].elem_type )
   {
     case PRO_E_TOOL_MTN_TYPE:
        break;

     case PRO_E_TOOL_MTN_CL_CMD:
        err = UserSimpleClCommandSet( cl_command_wstr, location_type,
                                      param, element );

        ERROR_CHECK( "UserToolMtnSimpleClCommandSet", 
                     "UserSimpleClCommandSet()", 
                     err );
        break;

     default:
        ProTKFprintf( stderr, "Error setting element type\n" );
        err = PRO_TK_GENERAL_ERROR;
        ERROR_CHECK( "UserToolMtnSimpleClCommandSet", 
                     "UserToolMtnSimpleClCommandSet()", 
                     err );
        break;
   }

   if ( elem_table[ii].val_type == PRO_VALUE_TYPE_INT )
   {
     err = ProElementIntegerSet(element,PRO_TM_TYPE_CL_COMMAND);
     ERROR_CHECK( "UserToolMtnSimpleClCommandSet", "ProElementIntegerSet()", 
                  err );
   }

   err = ProElemtreeElementAdd( tool_mtn_elem, NULL, element );
   ERROR_CHECK( "UserToolMtnSimpleClCommandSet", "ProElemtreeElementAdd", 
                err );
 }

 return ( err );
}

/*====================================================================*\
FUNCTION : UserToolMtnFollowCutSet
PURPOSE  : Set "Follow Cut" tool motion
\*====================================================================*/
ProError UserToolMtnFollowCutSet( 
/*--------------------------------------------------------------------*/
MfgPrmDblValue  dbl_params[],
int		n_dbl_params,
MfgPrmStrValue  str_params[],
int		n_str_params,
ProTmTrimValOpt trim_option,
double		start_value,
double		end_value,
ProBool		reverse_dir,
ProElement	tool_mtn_elem

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProElement		element;
 ProValueData		value_data;
 ProValue		value;
 ProSelection		selection;
 ProReference		reference;
 int			ii = 0, table_size = 0;
 static ElemTable	elem_table[] = 
 {
   { PRO_E_TOOL_MTN_TYPE,           PRO_VALUE_TYPE_INT    },
   { PRO_E_MFG_PARAM_ARR,           ARRAY                 },
   { PRO_E_TOOL_MTN_TRIM_VAL_OPT,   PRO_VALUE_TYPE_INT    },
   { PRO_E_TOOL_MTN_TRIM_START_VAL, PRO_VALUE_TYPE_DOUBLE },
   { PRO_E_TOOL_MTN_TRIM_END_VAL,   PRO_VALUE_TYPE_DOUBLE },
   { PRO_E_TOOL_MTN_TRIM_FLIP_DIR,  PRO_VALUE_TYPE_INT    }
 };

 table_size = sizeof( elem_table ) / sizeof( ElemTable );

 for ( ii = 0; ii < table_size; ii++ )
 {
   err = ProElementAlloc( elem_table[ii].elem_type, &element );
   ERROR_CHECK( "UserToolMtnFollowCutSet","ProElementAlloc()", err );

   switch ( elem_table[ii].elem_type )
   {
     case PRO_E_TOOL_MTN_TYPE:
        value_data.v.i = PRO_TM_TYPE_TRIM;
        break;

     case PRO_E_MFG_PARAM_ARR:
        err = UserMfgParamArrSet( dbl_params, n_dbl_params,
                                  str_params, n_str_params,
                                  element );
        ERROR_CHECK( "UserToolMtnFollowCutSet", "UserMfgParamArrSet()", 
                     err );
        break;

     case PRO_E_TOOL_MTN_TRIM_VAL_OPT:
        value_data.v.i = trim_option;
        break;

     case PRO_E_TOOL_MTN_TRIM_START_VAL:
        value_data.v.d = start_value;
        break;

     case PRO_E_TOOL_MTN_TRIM_END_VAL:
        value_data.v.d = end_value;
        break;

     case PRO_E_TOOL_MTN_TRIM_FLIP_DIR:
        value_data.v.i = (int)reverse_dir;
        break;

     default:
        ProTKFprintf( stderr, "Error setting element type\n" );
        err = PRO_TK_GENERAL_ERROR;
        ERROR_CHECK( "UserToolMtnFollowCutSet","UserToolMtnFollowCutSet()", 
                     err );
        break;
   }

   if ( elem_table[ii].val_type != ARRAY )
   {
     err = ProValueAlloc( &value );
     ERROR_CHECK( "UserToolMtnFollowCutSet","ProValueAlloc()", err );

     value_data.type = elem_table[ii].val_type;

     err = ProValueDataSet( value, &value_data );
     ERROR_CHECK( "UserToolMtnFollowCutSet", "ProValueDataSet()", err );

     err = ProElementValueSet( element, value );
     ERROR_CHECK( "UserToolMtnFollowCutSet", "ProElementValueSet()", err );
   }

   err = ProElemtreeElementAdd( tool_mtn_elem, NULL, element );
   ERROR_CHECK( "UserToolMtnFollowCutSet", "ProElemtreeElementAdd", err );
 }

 return ( err );
}

/*====================================================================*\
FUNCTION : UserToolMtnCurveCutSet
PURPOSE  : Set "Curve Cut" tool motion
\*====================================================================*/
ProError UserToolMtnCurveCutSet( 
/*--------------------------------------------------------------------*/
ProSelection	curve,
MfgPrmDblValue  dbl_params[],
int		n_dbl_params,
MfgPrmStrValue  str_params[],
int		n_str_params,
ProElement	tool_mtn_elem

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProElement		element;
 ProValueData		value_data;
 ProValue		value;
 ProSelection		selection;
 ProReference		reference;
 int			ii = 0, table_size = 0;
 static ElemTable	elem_table[] = 
 {
   { PRO_E_TOOL_MTN_TYPE, PRO_VALUE_TYPE_INT },
   { PRO_E_MFG_PARAM_ARR, ARRAY              },
   { PRO_E_MFG_TRAJ_CRV,  COMPOUND           },
   { PRO_E_MFG_OFFSET,    COMPOUND           }
 };

 table_size = sizeof( elem_table ) / sizeof( ElemTable );

 for ( ii = 0; ii < table_size; ii++ )
 {
   err = ProElementAlloc( elem_table[ii].elem_type, &element );
   ERROR_CHECK( "UserToolMtnCurveCutSet","ProElementAlloc()", err );

   switch ( elem_table[ii].elem_type )
   {
     case PRO_E_TOOL_MTN_TYPE:
        break;

     case PRO_E_MFG_PARAM_ARR:
        err = UserMfgParamArrSet( dbl_params, n_dbl_params,
                                  str_params, n_str_params,
                                  element );
        ERROR_CHECK( "UserToolMtnCurveCutSet", "UserMfgParamArrSet()", err );
        break;

     case PRO_E_MFG_TRAJ_CRV:
        err = UserTrajCurveSet( curve, element );
        ERROR_CHECK( "UserToolMtnCurveCutSet", "UserTrajCurveSet()", err );
        break;

     case PRO_E_MFG_OFFSET:
        err = UserMfgOffsetSet( PRO_B_TRUE, PRO_MAT_RMV_LEFT, PRO_B_TRUE, 
                                element );
        ERROR_CHECK( "UserToolMtnCurveCutSet", "UserMfgOffsetSet()", err );
        break;

     default:
        ProTKFprintf( stderr, "Error setting element type\n" );
        err = PRO_TK_GENERAL_ERROR;
        ERROR_CHECK( "UserToolMtnCurveCutSet", "UserToolMtnCurveCutSet()",
                     err );
        break;
   }

   if ( elem_table[ii].val_type == PRO_VALUE_TYPE_INT )
   {
     err = ProElementIntegerSet(element,PRO_TM_TYPE_CURVE_TRAJECTORY);
     ERROR_CHECK( "UserToolMtnCurveCutSet", "ProElementIntegerSet()", err );
   }

   err = ProElemtreeElementAdd( tool_mtn_elem, NULL, element );
   ERROR_CHECK( "UserToolMtnCurveCutSet", "ProElemtreeElementAdd", err );
 }

 return ( err );
}

/*====================================================================*\
FUNCTION : UserTrajToolMtnArrSet
PURPOSE  : Set array of tool motions for trajectory sequence
\*====================================================================*/
ProError UserTrajToolMtnArrSet( 
/*--------------------------------------------------------------------*/
ProSelection	curve,
ProElement	tm_arr_elem

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProElement		element;
 int			ii, num = 0;
 int			n_leadin_dbl_params;
 int			n_leadout_dbl_params;
 static ProTmType	tm_types[] =
 {
   PRO_TM_TYPE_PLUNGE,              /* optional */
   PRO_TM_TYPE_LEAD_IN,             /* optional */
   PRO_TM_TYPE_CURVE_TRAJECTORY,    /* trajectroy cut tool motion */
   PRO_TM_TYPE_TRIM,        /* required for PRO_TM_TYPE_CURVE_TRAJECTORY */
   PRO_TM_TYPE_LEAD_OUT,            /* optional */
   PRO_TM_TYPE_GO_RETRACT,          /* optional */
   PRO_TM_TYPE_CL_COMMAND,          /* optional */
 };
 static MfgPrmDblValue  leadin_dbl_params[] =
 {
   { "ENTRY_ANGLE",       90.0    },
   { "LEAD_RADIUS",       30.0    },
   { "TANGENT_LEAD_STEP", 40.0    },
   { "NORMAL_LEAD_STEP",  0.0     }
 };
 static MfgPrmDblValue  leadout_dbl_params[] =
 {
   { "EXIT_ANGLE",        90.0    },
   { "LEAD_RADIUS",       30.0    },
   { "TANGENT_LEAD_STEP", 0.0     },
   { "NORMAL_LEAD_STEP",  0.0     }
 };
 wchar_t		*cl_command_wstr = L"OPSTOP";

 n_leadin_dbl_params  = sizeof( leadin_dbl_params ) /sizeof( MfgPrmDblValue );
 n_leadout_dbl_params = sizeof( leadout_dbl_params )/sizeof( MfgPrmDblValue );

 num = sizeof( tm_types ) / sizeof( ProTmType );

 for ( ii = 0; ii < num; ii++ )
 {
   err = ProElementAlloc( PRO_E_TOOL_MTN, &element );
   ERROR_CHECK( "UserTrajToolMtnArrSet", "ProElementAlloc", err );

   switch ( tm_types[ii] )
   {
     case PRO_TM_TYPE_PLUNGE:
       err = UserToolMtnPlungeSet( NULL, 0, NULL, 0, 0., 0., 0., NULL, 
                                   element );
       ERROR_CHECK( "UserTrajToolMtnArrSet()", "UserToolMtnPlungeSet", err );
       break;

     case PRO_TM_TYPE_LEAD_IN:
       err = UserToolMtnLeadInSet( leadin_dbl_params, 
                                   n_leadin_dbl_params, 
                                   NULL, 
                                   0, 
                                   PRO_TM_DIR_RIGHT_SIDE, 
                                   NULL, 
                                   element );

       ERROR_CHECK( "UserTrajToolMtnArrSet()", "UserToolMtnLeadInSet", err );
       break;

     case PRO_TM_TYPE_CURVE_TRAJECTORY:
       err = UserToolMtnCurveCutSet( curve,
                                     NULL, 0,  /* use seq params */
                                     NULL, 0,
                                     element );
       ERROR_CHECK( "UserTrajToolMtnArrSet()", "UserToolMtnCurveCutSet", 
                    err );
       break;

     case PRO_TM_TYPE_TRIM:
       err = UserToolMtnFollowCutSet( NULL, 0,  /* use params from parent */
                                      NULL, 0,  /* use params from parent */
                                      PRO_TM_TRIM_VAL_PARAM,
                                      0.,
                                      1.,
                                      PRO_B_FALSE,
                                      element );
       ERROR_CHECK( "UserTrajToolMtnArrSet()", "UserToolMtnFollowCutSet", 
                    err );
       break;

     case PRO_TM_TYPE_LEAD_OUT:
       err = UserToolMtnLeadOutSet( leadout_dbl_params,
                                    n_leadout_dbl_params,
                                    NULL,
                                    0,
                                    PRO_TM_DIR_RIGHT_SIDE, 
                                    NULL,
                                    element );

       ERROR_CHECK( "UserTrajToolMtnArrSet()", "UserToolMtnLeadOutSet", err );
       break;

     case PRO_TM_TYPE_GO_RETRACT:
       err = UserToolMtnRetractSet( NULL, 0, NULL, 0, element );

       ERROR_CHECK( "UserTrajToolMtnArrSet()", "UserToolMtnRetractSet", err );
       break;

     case PRO_TM_TYPE_CL_COMMAND:
        err = UserToolMtnSimpleClCommandSet( cl_command_wstr, 
                                             PRO_CL_CMD_LOC_TYPE_CURR, 0., 
                                             element );

        ERROR_CHECK( "UserTrajToolMtnArrSet", "UserSimpleClCommandSet()", 
                     err );
        break;


     default:
       ProTKFprintf( stderr, "Error setting tool motion type\n" );
       err = PRO_TK_GENERAL_ERROR;
       ERROR_CHECK( "UserTrajToolMtnArrSet()", "UserTrajToolMtnArrSet", err );
       break;
   }

   err = ProElemtreeElementAdd( tm_arr_elem, NULL, element );
   ERROR_CHECK( "UserTrajToolMtnArrSet","ProElemtreeElementAdd", err );
 }

 return ( err );
}

/*====================================================================*\
FUNCTION : UserManualCycleMtnArrSet
PURPOSE  : Set array of tool motions for manual cycle sequence. 
           In this example the array has only one tool motion of type 
           PRO_TM_TYPE_CL_COMMAND
\*====================================================================*/
ProError UserManualCycleMtnArrSet( 
/*--------------------------------------------------------------------*/
ProElement	tm_arr_elem

)
/*--------------------------------------------------------------------*/
{
 ProError		err = PRO_TK_NO_ERROR;
 ProElement		element;
 int			ii, num = 0;
 static ProTmType	tm_types[] =
 {
   PRO_TM_TYPE_CL_COMMAND
 };
 wchar_t		*cl_command_str = L"DELAY/REV\nCOMMAND/1\nCOMMAND/2";

 num = sizeof( tm_types ) / sizeof( ProTmType );

 for ( ii = 0; ii < num; ii++ )
 {
   err = ProElementAlloc( PRO_E_TOOL_MTN, &element );
   ERROR_CHECK( "UserManualCycleMtnArrSet", "ProElementAlloc", err );

   switch ( tm_types[ii] )
   {
     case PRO_TM_TYPE_CL_COMMAND:
       err = UserToolMtnSimpleClCommandSet( cl_command_str, 
                                            PRO_CL_CMD_LOC_TYPE_CURR, 0.,
                                            element );
       ERROR_CHECK( "UserManualCycleMtnArrSet()", "UserToolMtnPlungeSet", 
                    err );
       break;

     default:
       ProTKFprintf( stderr, "Error setting tool motion type\n" );
       err = PRO_TK_GENERAL_ERROR;
       ERROR_CHECK( "UserManualCycleMtnArrSet()", "UserTrajToolMtnArrSet", 
                    err );
       break;
   }

   err = ProElemtreeElementAdd( tm_arr_elem, NULL, element );
   ERROR_CHECK( "UserManualCycleMtnArrSet","ProElemtreeElementAdd", err );
 }

 return ( err );
}