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

/*---------------------------------------------------------------------------*\
    Pro/TOOLKIT includes
\*---------------------------------------------------------------------------*/
#include <ProSelection.h>
#include <ProModelitem.h>
#include <ProColor.h>
#include <ProMessage.h>
#include <ProMenu.h>
#include <ProMdl.h>
#include <ProDrawing.h>
#include <ProUtil.h>
#include <ProCurvedata.h>
#include <ProDtlentity.h>
#include <ProDtlsymdef.h>
#include <ProGraphic.h>
#include <ProObjects.h>

/*---------------------------------------------------------------------------*\
    Application includes
\*---------------------------------------------------------------------------*/
#include "UtilMessage.h"
#include "UtilMenu.h"
#include "UtilFiles.h"
#include "UtilMath.h"
#include <ProTKRunTime.h>
/*---------------------------------------------------------------------------*\
    Application macros
\*---------------------------------------------------------------------------*/
#define ENT_COLOR     0
#define ENT_FONT      1
#define ENT_THICKNESS 2

#define SOLID_FONT    0
#define CTRL_FONT     1
#define DASH_FONT     2
#define DOT_FONT      3
#define PHANTOM_FONT  4

#define DTL_DRAW      0
#define DTL_ERASE     1
#define DTL_DELETE    2

#define DTL_ENTITY_FILE  ".ent"

int ProTestColorGet (ProColor *);

void ProTestColorPrint (FILE *, ProColor);
ProError ProTestEntGet (ProDrawing, ProDtlentity*, ProPoint3d);
ProError ProTestEntCreate (ProDrawing, ProDtlentitydata, ProCurvedata,
    ProDtlentity*);

/*===========================================================================*\
  Function : ProTestEntity
  Purpose  : 
\*===========================================================================*/
int ProTestEntity(ProDrawing* drawing)
{
    ProError err;
    int menu_id;
    ProDrawing draw = *drawing;
    int ProTestEntAdd(ProDrawing drw);
    int ProTestEntCopy(ProDrawing drw);
    int ProTestEntEdit(ProDrawing drw);
    int ProTestEntInfo(ProDrawing drw);
    int ProTestEntDisplay(ProDrawing drw);
        
    err = ProMenuFileRegister((char*)"Entity",(char*)"tkentity.mnu", &menu_id);
    err = ProMenubuttonActionSet((char*)"Entity",(char*)"Entity", 
		(ProMenubuttonAction)ProMenuDelete, NULL, 0);
    err = ProMenubuttonActionSet((char*)"Entity",(char*)"Create", 
		(ProMenubuttonAction)ProTestEntAdd, draw, 0);
    err = ProMenubuttonActionSet((char*)"Entity",(char*)"Copy", 
		(ProMenubuttonAction)ProTestEntCopy, draw, 0);
    err = ProMenubuttonActionSet((char*)"Entity",(char*)"Edit", 
		(ProMenubuttonAction)ProTestEntEdit, draw, 0);
#if 0                
    err = ProMenubuttonActionSet((char*)"Entity",(char*)"Info",  
                (ProMenubuttonAction)ProTestEntInfo, draw, 0);
#else
    err = ProMenubuttonActionSet((char*)"Entity",(char*)"Info",  
                (ProMenubuttonAction)ProMenuDelete, draw, 0);
#endif                
    err = ProMenubuttonActionSet((char*)"Entity",(char*)"Display",  
                (ProMenubuttonAction)ProTestEntDisplay, draw, 0);
    err = ProMenuCreate(PROMENUTYPE_MAIN, (char*)"Entity",&menu_id);
    err = ProMenuProcess((char*)"", &menu_id);
    
    return (0);
}

/*===========================================================================*\
  Function : ProTestEntAdd
  Purpose  : 
\*===========================================================================*/
int ProTestEntAdd(ProDrawing drw)
{
    ProError err;
    int opt, np, n;
    ProDtlentitydata ent_data;
    ProDtlentity entity;
    ProMouseButton btn;
    Pro3dPnt sel_pnt, end_pnt, start_pnt, *pnt_arr, chord, *p_tan, *tan_arr;
    ProVector vector1, vector2;
    ProCurvedata crv_data;
    double start_angle = 0.0, end_angle = 0.0, radius = 0.0;
    double angle = 0.0, maj_lenth = 0.0, min_lenth = 0.0, len = 0.0;
    double range[2] = {0.0, 90.0}, *par_arr;
    static ProUtilMenuButtons ent_opt[] = { 
        {"Create", 0, TEST_CALL_PRO_MENU_DELETE},
        {"Point",   PRO_ENT_POINT, 0},
        {"Line",    PRO_ENT_LINE, 0},
        {"Arc",     PRO_ENT_ARC, 0},
        {"Circle",  PRO_ENT_CIRCLE, 0},
        {"Spline",  PRO_ENT_SPLINE, 0},
        {"Ellipse", PRO_ENT_ELLIPSE, 0},
        {"",0,0}
    };
    err = ProUtilMenuIntValueSelect(ent_opt, &opt);
    err = ProDtlentitydataAlloc (drw, &ent_data);
    TEST_CALL_REPORT("ProDtlentitydataAlloc()",
        "ProTestEntAdd()", err, err != PRO_TK_NO_ERROR);  
    switch (opt)
    {
    case PRO_ENT_POINT :
        ProUtilMsgPrint("gen", "TEST %0s", "Select position:");
        err = ProMousePickGet(PRO_ANY_BUTTON, &btn, sel_pnt);
        if (btn != PRO_LEFT_BUTTON || err != PRO_TK_NO_ERROR)
            return(0);
        err = ProPointdataInit (sel_pnt, &crv_data);
        TEST_CALL_REPORT("ProPointdataInit()",
            "ProTestEntAdd()", err, err != PRO_TK_NO_ERROR);   
        
        break;
    case PRO_ENT_LINE :
        ProUtilMsgPrint("gen", "TEST %0s", "End points");
        err = ProMousePickGet(PRO_ANY_BUTTON, &btn, sel_pnt);
        if (btn != PRO_LEFT_BUTTON || err != PRO_TK_NO_ERROR)
            return(0);
        err = ProMousePickGet(PRO_ANY_BUTTON, &btn, end_pnt);
        if (btn != PRO_LEFT_BUTTON || err != PRO_TK_NO_ERROR)
            return(0);
        err = ProLinedataInit (sel_pnt, end_pnt, &crv_data); 
        TEST_CALL_REPORT("ProLinedataInit()",
            "ProTestEntAdd()", err, err != PRO_TK_NO_ERROR);   
        
        break;
    case PRO_ENT_ARC :
        ProUtilMsgPrint("gen", "TEST %0s", "Select center");
        err = ProMousePickGet(PRO_ANY_BUTTON, &btn, sel_pnt);
        if (btn != PRO_LEFT_BUTTON || err != PRO_TK_NO_ERROR)
            return(0);
        ProGraphicsCircleDraw( sel_pnt, 0.5);
        ProUtilMsgPrint("gen", "TEST %0s", "Select start point");
        err = ProMousePickGet(PRO_ANY_BUTTON, &btn, start_pnt);
        if (btn != PRO_LEFT_BUTTON || err != PRO_TK_NO_ERROR)
            return(0);
        ProGraphicsCircleDraw( start_pnt, 0.5);
        ProUtilVectorDiff (sel_pnt, start_pnt, end_pnt);
        radius = ProUtilVectorLength (end_pnt);
        
        ProUtilVectorDiff (start_pnt, sel_pnt, vector1);
        ProUtilVectorNormalize (vector1, vector1);
        ProUtilMsgPrint("gen", "TEST %0s", "Select end point");
        err = ProMousePickGet(PRO_ANY_BUTTON, &btn, end_pnt);
        if (btn != PRO_LEFT_BUTTON || err != PRO_TK_NO_ERROR)
            return(0);
        ProGraphicsCircleDraw(end_pnt, 0.5);
        vector2[0] =- vector1[1];
        vector2[1] = vector1[0];
        vector2[2] = 0;
        start_angle = atan2(start_pnt[1] - sel_pnt[1],
            start_pnt[0] - sel_pnt[0]);
        end_angle = atan2(end_pnt[1] - sel_pnt[1], end_pnt[0] - sel_pnt[0]);
        if(end_angle < 0.0)
            end_angle += TWOPI;
        
        err = ProArcdataInit (vector1, vector2, sel_pnt, start_angle,
            end_angle, radius, &crv_data);
        TEST_CALL_REPORT("ProArcdataInit()",
            "ProTestEntAdd()", err, err != PRO_TK_NO_ERROR);   
        
        break;
    case PRO_ENT_CIRCLE :
        ProUtilMsgPrint("gen", "TEST %0s", "Select center");
        err = ProMousePickGet(PRO_ANY_BUTTON, &btn, sel_pnt);
        if (btn != PRO_LEFT_BUTTON || err != PRO_TK_NO_ERROR)
            return(0);
        ProUtilMsgPrint("gen", "TEST %0s", "Select perimeter point");
        err = ProMousePickGet(PRO_ANY_BUTTON, &btn, start_pnt);
        if (btn != PRO_LEFT_BUTTON || err != PRO_TK_NO_ERROR)
            return(0);
        ProUtilVectorDiff (sel_pnt, start_pnt, end_pnt);
        radius = ProUtilVectorLength (end_pnt);
        vector1[0] = 1.0;
        vector1[1] = 0.0;
        vector1[2] = 0.0;
        vector2[0] = 0.0;
        vector2[1] = 1.0;
        vector2[2] = 0.0;
        start_angle = 0.0;
        end_angle = TWOPI;
        err = ProArcdataInit (vector1, vector2, sel_pnt, start_angle,
            end_angle, radius, &crv_data);
        TEST_CALL_REPORT("ProArcdataInit()",
            "ProTestEntAdd()", err, err != PRO_TK_NO_ERROR);   
            
        break;
    case PRO_ENT_SPLINE :
        err = ProArrayAlloc (0, sizeof(ProPoint3d), 1, (ProArray*)&pnt_arr);
        ProUtilMsgPrint("gen", "TEST %0s", "Select points");
        while (1)
        {
            err = ProMousePickGet(PRO_ANY_BUTTON, &btn, sel_pnt);
            if (btn != PRO_LEFT_BUTTON || err != PRO_TK_NO_ERROR)
                break;
            ProGraphicsCircleDraw( sel_pnt, 0.5);
            err = ProArrayObjectAdd( (ProArray*)&pnt_arr, PRO_VALUE_UNUSED, 
                1, sel_pnt);
        }
        err = ProArraySizeGet ((ProArray)pnt_arr, &np);
        if (err != PRO_TK_NO_ERROR || np == 0)
            return (0);
        err = ProArrayAlloc (0, sizeof(ProPoint3d), 1, (ProArray*)&p_tan);
        err = ProArrayAlloc (0, sizeof(double), 1, (ProArray*)&par_arr);
        tan_arr = (ProPoint3d*)calloc(np, sizeof(ProPoint3d));
        tan_arr[0][0] = pnt_arr[1][0] - pnt_arr[0][0];
        tan_arr[0][1] = 2 * pnt_arr[1][1] - pnt_arr[2][1] - pnt_arr[0][1];
        tan_arr[np-1][0] = -(pnt_arr[np-2][0] - pnt_arr[np-1][0]);
        tan_arr[np-1][1] = -(2 * pnt_arr[np-2][1] - pnt_arr[np-3][1] - 
            pnt_arr[np-1][1]);
            
        for(n = 1; n < np-1; n++)
        {
            tan_arr[n][0] = pnt_arr[n+1][0] - pnt_arr[n-1][0];
            tan_arr[n][1] = pnt_arr[n+1][1] - pnt_arr[n-1][1]; 
        }
        for (n = 0; n < np; n++)
        {
            len = (tan_arr[n][0]*tan_arr[n][0])+(tan_arr[n][1]*tan_arr[n][1]);
            len = sqrt(len);
            tan_arr[n][0] /= len;
            tan_arr[n][1] /= len;
            err = ProArrayObjectAdd ((ProArray*)&p_tan, PRO_VALUE_UNUSED,
                1, tan_arr[n]);
        }
        angle = 0.0;
        err = ProArrayObjectAdd ((ProArray*)&par_arr, PRO_VALUE_UNUSED,
            1, &angle);
        for (n = 1; n < np; n++)
        {
            ProUtilVectorDiff (pnt_arr[n], pnt_arr[n-1], chord);
            angle = ProUtilVectorLength(chord) + par_arr[n-1];
            err = ProArrayObjectAdd ((ProArray*)&par_arr, PRO_VALUE_UNUSED,
                1, &angle);
        }
        err = ProSplinedataInit (par_arr, pnt_arr, p_tan, np, &crv_data);
         TEST_CALL_REPORT("ProSplinedataInit()",
            "ProTestEntAdd()", err, err != PRO_TK_NO_ERROR);
        err = ProArrayFree ((ProArray*)&p_tan);
        err = ProArrayFree ((ProArray*)&par_arr);
        err = ProArrayFree ((ProArray*)&pnt_arr);
       
        break;
    case PRO_ENT_ELLIPSE :
        ProUtilMsgPrint("gen", "TEST %0s", "Enter ends of major axis");
        err = ProMousePickGet(PRO_ANY_BUTTON, &btn, start_pnt);
        if (btn != PRO_LEFT_BUTTON || err != PRO_TK_NO_ERROR)
            return(0);
        ProGraphicsCircleDraw( start_pnt, 0.5);
        err = ProMousePickGet(PRO_ANY_BUTTON, &btn, end_pnt);
        if (btn != PRO_LEFT_BUTTON || err != PRO_TK_NO_ERROR)
            return(0);
        ProGraphicsCircleDraw( end_pnt, 0.5);
        sel_pnt[0] = (start_pnt[0] + end_pnt[0]) / 2.0;
        sel_pnt[1] = (start_pnt[1] + end_pnt[1]) / 2.0;
        sel_pnt[2] = 0.0;
        
        ProUtilMsgPrint("gen", "TEST %0s", "Enter the rotation angle");
        if (ProMessageDoubleRead (range, &angle) != PRO_TK_NO_ERROR)
            return(0);
        ProUtilVectorDiff (end_pnt, sel_pnt, vector1);
        maj_lenth = ProUtilVectorLength (vector1);
        ProUtilVectorNormalize(vector1, vector1);
        vector2[0] = 0.0;
        vector2[1] = 0.0;
        vector2[2] = 1.0;
        min_lenth = maj_lenth * cos(angle * TWOPI /360);
        start_angle = 0.0;
        end_angle = TWOPI;
        err = ProEllipsedataInit (sel_pnt, vector1, vector2, min_lenth, 
            maj_lenth, start_angle, end_angle, &crv_data);
        TEST_CALL_REPORT("ProEllipsedataInit()",
            "ProTestEntAdd()", err, err != PRO_TK_NO_ERROR);
               
        break;
    }
    err = ProTestEntCreate (drw, ent_data, crv_data, &entity);
    err = ProDtlentitydataFree(ent_data);
    TEST_CALL_REPORT("ProDtlentitydataFree()",
        "ProTestEntAdd()", err, err != PRO_TK_NO_ERROR); 
    return (0);
}

/*===========================================================================*\
  Function : ProTestEntCreate
  Purpose  : 
\*===========================================================================*/
ProError ProTestEntCreate (ProDrawing drw,
                           ProDtlentitydata ent_data,
                           ProCurvedata crv_data, 
                           ProDtlentity *entity)
{
    ProError err;
    int sheet = 0;
    ProView over_view;
     
    err = ProDtlentitydataCurveSet (ent_data, &crv_data);
    TEST_CALL_REPORT("ProDtlentitydataCurveSet()",
        "ProTestEntCreate()", err, err != PRO_TK_NO_ERROR);
    err = ProDrawingCurrentSheetGet (drw, &sheet);
    TEST_CALL_REPORT("ProDrawingCurrentSheetGet()",
        "ProTestEntCreate()", err, err != PRO_TK_NO_ERROR);
    err = ProDrawingBackgroundViewGet (drw, sheet, &over_view);
    TEST_CALL_REPORT("ProDrawingBackgroundViewGet()",
        "ProTestEntCreate()", err, err != PRO_TK_NO_ERROR);
    err = ProDtlentitydataViewSet (ent_data, over_view);
    TEST_CALL_REPORT("ProDtlentitydataViewSet()",
        "ProTestEntCreate()", err, err != PRO_TK_NO_ERROR);
    err = ProDtlentityCreate (drw, NULL, ent_data, entity);
    TEST_CALL_REPORT("ProDtlentityCreate()",
        "ProTestEntCreate()", err, err != PRO_TK_NO_ERROR);
    if (err != PRO_TK_NO_ERROR)
        return (err);
    err = ProDtlentityDraw(entity);
    TEST_CALL_REPORT("ProDtlentityDraw()",
        "ProTestEntCreate()", err, err != PRO_TK_NO_ERROR);
   
    return (err);
}

/*===========================================================================*\
  Function : ProTestEntCopy
  Purpose  : 
\*===========================================================================*/
int ProTestEntCopy (ProDrawing drw)
{
    ProError err;
    ProDtlentity entity;
    int  i;
    ProDtlentitydata entdata;
    ProCurvedata crv_data;
    ProEnttype crv_type;
    ProMouseButton btn;
    Pro3dPnt move, sel_pnt, pos;
    
    err = ProTestEntGet (drw, &entity, pos);
    if (err != PRO_TK_NO_ERROR)
        return (0);
    err = ProDtlentityDataGet (&entity, NULL, &entdata);
    TEST_CALL_REPORT("ProDtlentityDataGet()",
        "ProTestEntCopy()", err, err != PRO_TK_NO_ERROR);   
    ProUtilMsgPrint("gen", "TEST %0s", "Select new position");
    if(ProMousePickGet(PRO_ANY_BUTTON, &btn, sel_pnt) != PRO_TK_NO_ERROR)
        return (0);
    err = ProDtlentitydataCurveGet (entdata, &crv_data);
    TEST_CALL_REPORT("ProDtlentitydataCurveGet()",
        "ProTestEntCopy()", err, err != PRO_TK_NO_ERROR);   
    err = ProCurvedataTypeGet(&crv_data, &crv_type);
    TEST_CALL_REPORT("ProCurvedataTypeGet()",
        "ProTestEntCopy()", err, err != PRO_TK_NO_ERROR);
    ProUtilVectorDiff (sel_pnt, pos, move); 
    switch (crv_type)
    {
    case PRO_ENT_POINT :
        ProUtilVectorSum (crv_data.point.position, move, 
            crv_data.point.position);
        break;
    case PRO_ENT_LINE :
        ProUtilVectorSum (crv_data.line.end1, move, crv_data.line.end1);
        ProUtilVectorSum (crv_data.line.end2, move, crv_data.line.end2);
        break;
    case PRO_ENT_ARC :
        ProUtilVectorSum(crv_data.arc.origin, move, crv_data.arc.origin);
        break;
    case PRO_ENT_SPLINE :
        for(i = 0; i < crv_data.spline.num_points; i++)
            ProUtilVectorSum(crv_data.spline.pnt_arr[i], move,
                crv_data.spline.pnt_arr[i]);
        break;
    case PRO_ENT_ELLIPSE :
        ProUtilVectorSum(crv_data.ellipse.center, move,
            crv_data.ellipse.center);
        break;
    default :
        return (0);
    }
    err = ProTestEntCreate (drw, entdata, crv_data, &entity);
    err = ProDtlentitydataFree( entdata );
    TEST_CALL_REPORT("ProDtlentitydataFree()",
        "ProTestEntCopy()", err, err != PRO_TK_NO_ERROR);   
    return (0);
}

/*===========================================================================*\
  Function : ProTestNewEntCreate
  Purpose  : 
\*===========================================================================*/
 ProError ProTestEntGet (ProDrawing drw, 
                         ProDtlentity *entity,
                         ProPoint3d  pos)
{
    ProError err = PRO_TK_NO_ERROR;    
    ProSelection *sel;
    int n_sel;
        
    ProUtilMsgPrint("gen", "TEST %0s", "Select an entity");
    
    if (ProSelect((char*)"draft_ent", 1, NULL, NULL, NULL, NULL, &sel, &n_sel)!= PRO_TK_NO_ERROR)
        return PRO_TK_GENERAL_ERROR;
        
    err = ProSelectionModelitemGet (sel[0], entity);
    if (err != PRO_TK_NO_ERROR)
    	return err;
    
    if (pos != NULL)
    {
       err = ProSelectionPoint3dGet(sel[0], pos);
       if (err != PRO_TK_NO_ERROR)
    	   return err;
    }           
    
    return (err);
}

/*===========================================================================*\
  Function : ProTestFontGet
  Purpose  : 
\*===========================================================================*/
int ProTestFontGet(ProName font)
{
    ProError err;
    int opt;
    static ProUtilMenuButtons font_type[] = { 
        {"Font", 0, TEST_CALL_PRO_MENU_DELETE},
        {"Solid", SOLID_FONT, 0},
        {"Ctrl", CTRL_FONT, 0},
        {"Dot", DOT_FONT, 0},
        {"Phantom", PHANTOM_FONT, 0},
        {"Dash", DASH_FONT, 0},
        {"",0,0}
    };
    err = ProUtilMenuIntValueSelect(font_type, &opt);
    switch (opt)
    {
    case SOLID_FONT :
        ProStringToWstring(font, (char*)"SOLIDFONT");
        break;
    case CTRL_FONT:
        ProStringToWstring(font, (char*)"CTRLFONT");
        break;
    case PHANTOM_FONT:
        ProStringToWstring(font, (char*)"PHANTOMFONT");
        break;
    case DOT_FONT:
        ProStringToWstring(font, (char*)"DOTFONT");
        break;
    case DASH_FONT:
        ProStringToWstring(font, (char*)"DASHFONT");
        break;
    }
    return (0);
}

/*===========================================================================*\
  Function : ProTestEntEdit
  Purpose  : 
\*===========================================================================*/
int ProTestEntEdit(ProDrawing drw)
{
    ProError err;
    int opt;
    ProColor color;
    ProDtlentity entity;
    ProDtlsymdef *symbol = NULL;
    ProDtlentitydata ent_data;
    ProName font;
    ProCharLine line;
    double width = 0.0;
    
    static ProUtilMenuButtons edit_opt[] = { 
        {"Edit", 0, TEST_CALL_PRO_MENU_DELETE},
        {"Color", ENT_COLOR, 0},
        {"Font", ENT_FONT, 0},
        {"Thickness", ENT_THICKNESS, 0},
        {"",0,0}
    };
    err = ProTestEntGet (drw, &entity, NULL);
    if (err != PRO_TK_NO_ERROR)
        return (err);
    err = ProDtlentityDataGet (&entity, symbol, &ent_data);
    TEST_CALL_REPORT("ProDtlentityDataGet()",
        "ProTestEntEdit()", err, err != PRO_TK_NO_ERROR);
    err = ProUtilMenuIntValueSelect(edit_opt, &opt);
    switch (opt)
    {
    case ENT_COLOR :
        ProTestColorGet (&color);
        err = ProDtlentitydataColorSet (ent_data, &color);
        TEST_CALL_REPORT("ProDtlentitydataColorSet()",
            "ProTestEntEdit()", err, err != PRO_TK_NO_ERROR);
        break;
    case ENT_FONT :
        ProTestFontGet (font);
        err = ProDtlentitydataFontSet (ent_data, font);
        TEST_CALL_REPORT("ProDtlentitydataFontSet()",
            "ProTestEntEdit()", err, err != PRO_TK_NO_ERROR);
        break;
    case ENT_THICKNESS :
        err = ProDtlentitydataWidthGet (ent_data, &width);
        ProTKSprintf (line, "Enter width [%6.2f]", width);
        ProUtilMsgPrint("gen", "TEST %0s", line);
        if (ProMessageDoubleRead (NULL, &width) != PRO_TK_NO_ERROR)
            return (0);
        err = ProDtlentitydataWidthSet (ent_data, width);
        TEST_CALL_REPORT("ProDtlentitydataWidthSet()",
            "ProTestEntEdit()", err, err != PRO_TK_NO_ERROR);
        break;
    }
    err = ProDtlentityErase (&entity);
    TEST_CALL_REPORT("ProDtlentityErase()",
        "ProTestEntEdit()", err, err != PRO_TK_NO_ERROR);
    err = ProDtlentityModify (&entity, symbol, ent_data);
    TEST_CALL_REPORT("ProDtlentityModify()",
        "ProTestEntEdit()", err, err != PRO_TK_NO_ERROR);
    err = ProDtlentityDraw (&entity);
    TEST_CALL_REPORT("ProDtlentityDraw()",
        "ProTestEntEdit()", err, err != PRO_TK_NO_ERROR);
    err = ProDtlentitydataFree( ent_data );
    TEST_CALL_REPORT("ProDtlentitydataFree()",
        "ProTestEntEdit()", err, err != PRO_TK_NO_ERROR);
    return (0);
}

/*===========================================================================*\
  Function : ProTestColorGet
  Purpose  : 
\*===========================================================================*/
int ProTestColorGet(ProColor *color)
{
    ProError err;
    int opt;
    double range[2] = {0.0, 1.0};
    static ProUtilMenuButtons method_type[] = { 
        {"Method", 0, TEST_CALL_PRO_MENU_DELETE},
        {"Default", PRO_COLOR_METHOD_DEFAULT, 0},
        {"Type", PRO_COLOR_METHOD_TYPE, 0},
        {"RGB", PRO_COLOR_METHOD_RGB, 0},
        {"",0,0}
    };
    static ProUtilMenuButtons color_type[] = { 
        {"-Color", 0, TEST_CALL_PRO_MENU_DELETE},
        {"Yellow", PRO_COLOR_LETTER, 0},
        {"Red",PRO_COLOR_HIGHLITE, 0},
        {"White", PRO_COLOR_DRAWING, 0},
        {"Background", PRO_COLOR_BACKGROUND, 0},
        {"Grey", PRO_COLOR_HALF_TONE , 0},
        {"Blue", PRO_COLOR_EDGE_HIGHLIGHT,0},
        {"Grey", PRO_COLOR_DIMMED, 0},
        {"Magenta", PRO_COLOR_ERROR , 0},
        {"Cyan", PRO_COLOR_WARNING , 0},
        {"Green", PRO_COLOR_SHEETMETAL, 0},
        {"Brown", PRO_COLOR_CURVE, 0},
        {"MAX", PRO_COLOR_MAX, 0},
        {"",0,0}
    };
    err = ProUtilMenuIntValueSelect(method_type, &opt);
    switch (opt)
    {
    case PRO_COLOR_METHOD_DEFAULT :
        color->method = PRO_COLOR_METHOD_DEFAULT;
        
        break;
    case PRO_COLOR_METHOD_TYPE :
        color->method = PRO_COLOR_METHOD_TYPE;
        ProUtilMenuIntValueSelect(color_type, (int*)&(color->value.type));
        
        break;
    case PRO_COLOR_METHOD_RGB :
        color->method = PRO_COLOR_METHOD_RGB;
        ProUtilMsgPrint("gen", "TEST %0s", "Enter red color factor:");
        if (ProMessageDoubleRead (range, &(color->value.map.red)) != 
            PRO_TK_NO_ERROR)
                color->value.map.red = 0.9;
        ProUtilMsgPrint("gen", "TEST %0s", "Enter green color factor:");
        if (ProMessageDoubleRead (range, &(color->value.map.green)) != 
            PRO_TK_NO_ERROR)
                color->value.map.green = 0.05;
        ProUtilMsgPrint("gen", "TEST %0s", "Enter blue color factor:");
        if (ProMessageDoubleRead (range, &(color->value.map.blue)) != 
            PRO_TK_NO_ERROR)
                color->value.map.blue = 0.05;
                
        break;
    }
    return (0);
}
/*===========================================================================*\
  Function : ProTestEntDisplay
  Purpose  : 
\*===========================================================================*/
int ProTestEntDisplay(ProDrawing draw)
{
    ProError err;
    int opt, size = 0, i;
    ProDtlsymdef *symbol = NULL;
    ProDtlentity entity, *ent_arr = NULL;
    static ProUtilMenuButtons disp_type[] = { 
        {"Display", 0,          TEST_CALL_PRO_MENU_DELETE},
        {"Draw",    DTL_DRAW,   0},
        {"Erase",   DTL_ERASE,  0},
        {"Delete",  DTL_DELETE, 0},
        {"",        0,          0}
    };
    
    err = ProUtilMenuIntValueSelect(disp_type, &opt);
    
    switch (opt)
    {
#if 0    
    case DTL_DRAW :
        err = ProDrawingDtlentitiesCollect (draw, symbol, 1, &ent_arr);
        TEST_CALL_REPORT("ProDrawingDtlentitiesCollect()","ProTestEntDisplay()",
            err, err != PRO_TK_NO_ERROR && err != PRO_TK_E_NOT_FOUND);
        if (err != PRO_TK_NO_ERROR)
            break;
        err = ProArraySizeGet((ProArray)ent_arr, &size);
        for (i = 0; i < size; i++)
        {
            err = ProDtlentityDraw (&ent_arr[i]);
            TEST_CALL_REPORT("ProDtlentityDraw()",
                "ProTestEntDisplay()", err, err != PRO_TK_NO_ERROR);   
        }
        err = ProArrayFree ((ProArray*)&ent_arr);
        break;
#endif        
    case DTL_ERASE :
        err = ProTestEntGet (draw, &entity, NULL);
        if(err != PRO_TK_NO_ERROR)
            return err;
        err = ProDtlentityErase(&entity);
        TEST_CALL_REPORT("ProDtlentityErase()",
            "ProTestEntDisplay()", err, err != PRO_TK_NO_ERROR);
        
        break;
    case DTL_DELETE :
        err = ProTestEntGet (draw, &entity, NULL);
        if(err != PRO_TK_NO_ERROR)
            return err;
        err = ProDtlentityDelete (&entity, symbol);
        TEST_CALL_REPORT("ProDtlentityDelete()",
            "ProTestEntDisplay()", err, err != PRO_TK_NO_ERROR);
        
        break;
    }
    return (0);
}

/*===========================================================================*\
  Function : ProTestEntInfo
  Purpose  : 
\*===========================================================================*/
int ProTestEntInfo(ProDrawing drw)
{
    ProError err;
    ProDtlsymdef *symbol = NULL;
    ProDtlentity *dtl_ent_arr;
    int i, size = 0, ent_id = -1;
    ProDtlentitydata ent_data;
    ProCurvedata crv_data;
    ProColor color;
    ProName font;
    double width = 0.0;
    FILE  *fp;
    ProCharLine fname, string;
    ProEnttype crv_type = (ProEnttype)0;
    
    fp = ProUtilGenFilePtr((ProMdl)drw, (char*)DTL_ENTITY_FILE, fname, (char*)"w");
    
    err = ProDrawingDtlentitiesCollect (drw, symbol, PRO_VALUE_UNUSED,
        &dtl_ent_arr);
    TEST_CALL_REPORT("ProDrawingDtlentitiesCollect()","ProTestEntInfo()", 
        err, err != PRO_TK_NO_ERROR && err != PRO_TK_E_NOT_FOUND);    
    if (err != PRO_TK_NO_ERROR)
        return (0);        
    err = ProArraySizeGet ((ProArray)dtl_ent_arr, &size);
    ProTKPrintf ("\n\t size = %d", size);
    ProTKFprintf(fp, "File name : %s\n", fname);
    ProTKFprintf(fp, "Id\tType\tFont\t\tWidth\tColor\n");
    for (i = 0; i < size; i++)
    {
        err = ProDtlentityDataGet(&dtl_ent_arr[i], NULL, &ent_data);
        TEST_CALL_REPORT("ProDtlentityDataGet()",
            "ProTestEntInfo()", err, err != PRO_TK_NO_ERROR);

        err = ProDtlentitydataIdGet (ent_data, &ent_id);
        TEST_CALL_REPORT("ProDtlentitydataIdGet()",
            "ProTestEntInfo()", err, err != PRO_TK_NO_ERROR);
        
        err = ProDtlentitydataCurveGet (ent_data, &crv_data);
        TEST_CALL_REPORT("ProDtlentitydataCurveGet()",
            "ProTestEntInfo()", err, err != PRO_TK_NO_ERROR);
        
        err = ProCurvedataTypeGet (&crv_data, &crv_type);
        TEST_CALL_REPORT("ProCurvedataTypeGet()",
            "ProTestEntInfo()", err, err != PRO_TK_NO_ERROR);
        
        err = ProDtlentitydataColorGet (ent_data, &color);
        TEST_CALL_REPORT("ProDtlentitydataColorGet()",
            "ProTestEntInfo()", err, err != PRO_TK_NO_ERROR);
        
        err = ProDtlentitydataFontGet (ent_data, font);
        TEST_CALL_REPORT("ProDtlentitydataFontGet()",
            "ProTestEntInfo()", err, err != PRO_TK_NO_ERROR);
        
        err = ProDtlentitydataWidthGet (ent_data, &width);
        TEST_CALL_REPORT("ProDtlentitydataWidthGet()",
            "ProTestEntInfo()", err, err != PRO_TK_NO_ERROR);
        ProWstringToString (string, font);
        ProTKFprintf(fp, "%d\t%d\t%s\t%5.3f\t",ent_id, crv_type, string, 
            width);
        ProTestColorPrint (fp, color);
	err = ProDtlentitydataFree( ent_data );
	TEST_CALL_REPORT("ProDtlentitydataFree()",
			 "ProTestEntInfo()", err, err != PRO_TK_NO_ERROR);
    }
    fclose (fp);
    ProStringToWstring(font, fname);
    err = ProInfoWindowDisplay(font, NULL, NULL);
    err = ProArrayFree ((ProArray*)&dtl_ent_arr);
    return (0);
}

/*===========================================================================*\
  Function : ProTestColorPrint 
  Purpose  : 
\*===========================================================================*/
void ProTestColorPrint (FILE *fp, ProColor color)
{
    switch (color.method)
    {
    case PRO_COLOR_METHOD_DEFAULT :
        ProTKFprintf(fp, "Default\n");
        break;
    case PRO_COLOR_METHOD_TYPE :
        ProTKFprintf(fp, "Type: %d\n", color.value.type);
        break;
    case PRO_COLOR_METHOD_RGB :
        ProTKFprintf(fp, "red:%5.3f green:%5.3f blue:%5.3f\n",
            color.value.map.red, color.value.map.green,
                color.value.map.blue);
        break;
    default :
        ProTKFprintf(fp, "\n");
    break;
    }
}