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


/*--------------------------------------------------------------------*\
Pro/DEVELOP includes
\*--------------------------------------------------------------------*/


/*--------------------------------------------------------------------*\
Pro/TOOLKIT includes
\*--------------------------------------------------------------------*/
#include "ProToolkit.h"
#include "ProArray.h"
#include "ProMenu.h"
#include "ProMessage.h"

#include "ProTKRunTime.h"
#include "TestGenedata.h"
#include "TestFiletypes.h"
#include "UtilString.h"
#include <ProUtil.h>

/*--------------------------------------------------------------------*\
C System includes
\*--------------------------------------------------------------------*/
#include "math.h"
#include "ctype.h"
/*--------------------------------------------------------------------*\
Application macros
\*--------------------------------------------------------------------*/
#define  MAX_SLOT_CLASS_NUM  	2000

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


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


/*--------------------------------------------------------------------*\
Application static data/function
\*--------------------------------------------------------------------*/
static int ProTestSelectSlot(
        ProExtdataClass *data_class,
        int             *keyby,
        ProExtdataSlot  *data_slot);

static int ProTestSelectClass(
        ProMdl p_model,
        ProExtdataClass *p_class);

static int ProTestUserAction(
        char *dummy,
        int action);

static int ProTestGetDataType(
	);

static unsigned char ProTestHexToByte(
	char *str);


/*====================================================================*\
  Function : ProTestProAppdataErr
  Purpose  : Display error message
\*====================================================================*/
char *ProTestProAppdataErr(
	ProExtdataErr err)
{
     switch(err)
     {
         case PROEXTDATA_TK_NO_ERROR			:
 	    return((char*)"No error");
	 case PROEXTDATA_TK_INVALID_OBJ_OR_CLASS	:
            return((char*)"Invalid object or class");
	 case PROEXTDATA_TK_CLASS_OR_SLOT_EXISTS	:
            return((char*)"Class or slot exists");
	 case PROEXTDATA_TK_NAMES_TOO_LONG		:
            return((char*)"Names too long");
	 case PROEXTDATA_TK_SLOT_NOT_FOUND	  	:
	    return((char*)"Slot not found");
         case PROEXTDATA_TK_BAD_KEY_BY_FLAG		:
            return((char*)"Bay KEY_BY flag");
         case PROEXTDATA_TK_INVALID_OBJ_TYPE		:
            return((char*)"Invalid object type");
	 case PROEXTDATA_TK_EMPTY_SLOT			:
            return((char*)"Empty slot");
         case PROEXTDATA_TK_BAD_DATA_ARGS		:
            return((char*)"Bad data arguments");
	 case PROEXTDATA_TK_STREAM_TOO_LARGE	 	:
            return((char*)"Stream too large");
         case PROEXTDATA_TK_INVALID_SLOT_NAME	  	:
            return((char*)"Invalid slot name");
	 case PROEXTDATA_TK_ERROR			:
            return((char*)"General error");
         default :
            return((char*)"**UNKNOWN STATUS**");
     }
}


/*====================================================================*\
  Function : ProTestGeneData
  Purpose  : Display the generic data menu
\*====================================================================*/
int ProTestGeneData()
{
  ProMdl  model;
  ProError status;
  ProExtdataErr err;
  int id;

  status = ProMdlCurrentGet(&model);
  TEST_CALL_REPORT("ProMdlCurrentGet()", "ProTestGeneData( )",
                                status, status != PRO_TK_NO_ERROR);

  err = ProExtdataInit(model);
  TEST_CALL_REPORT("ProExtdataInit()", "ProTestGeneData()", 
 		(ProError)err, err != PROEXTDATA_TK_NO_ERROR);

  status = ProMenuFileRegister((char*)"TkGenData", (char*)"tkgendata.mnu", &id);
  TEST_CALL_REPORT("ProMenuFileRegister()", "ProTestGeneData()", 
				status, status != PRO_TK_NO_ERROR);
  status = ProMenubuttonActionSet((char*)"TkGenData",(char*)"-Register Class", 
      (ProMenubuttonAction)ProTestRegClass, model, 0);
  TEST_CALL_REPORT("ProMenubuttonActionSet()", "ProTestGeneData()", 
				status, status != PRO_TK_NO_ERROR);
  status = ProMenubuttonActionSet((char*)"TkGenData",(char*)"-Create Slot", 
      (ProMenubuttonAction)ProTestCreateSlot ,model, 0);
  TEST_CALL_REPORT("ProMenubuttonActionSet()", "ProTestGeneData()", 
				status, status != PRO_TK_NO_ERROR);
  status = ProMenubuttonActionSet((char*)"TkGenData",(char*)"-Write/Read Check", 
      (ProMenubuttonAction)ProTestWrCheck, model, 0);
  TEST_CALL_REPORT("ProMenubuttonActionSet()", "ProTestGeneData()", 
				status, status != PRO_TK_NO_ERROR);
  status = ProMenubuttonActionSet((char*)"TkGenData",(char*)"-Delete class", 
      (ProMenubuttonAction)ProTestDeleteC, model, 0);
  TEST_CALL_REPORT("ProMenubuttonActionSet()", "ProTestGeneData()", 
				status, status != PRO_TK_NO_ERROR);
  status = ProMenubuttonActionSet((char*)"TkGenData",(char*)"-Delete slot", 
      (ProMenubuttonAction)ProTestDelete, model, 0);
  TEST_CALL_REPORT("ProMenubuttonActionSet()", "ProTestGeneData()", 
				status, status != PRO_TK_NO_ERROR);
  status = ProMenubuttonActionSet((char*)"TkGenData",(char*)"-Dump", 
      (ProMenubuttonAction)ProTestDump, model, 0);
  TEST_CALL_REPORT("ProMenubuttonActionSet()", "ProTestGeneData()", 
				status, status != PRO_TK_NO_ERROR);
  status = ProMenubuttonActionSet((char*)"TkGenData",(char*)"-Random", 
      (ProMenubuttonAction)ProTestRandom, model, 0);
  TEST_CALL_REPORT("ProMenubuttonActionSet()", "ProTestGeneData()", 
				status, status != PRO_TK_NO_ERROR);
  status = ProMenubuttonActionSet((char*)"TkGenData",(char*)"-Refresh data",
      (ProMenubuttonAction)ProTestRefresh, model, 0);
  TEST_CALL_REPORT("ProMenubuttonActionSet()", "ProTestGeneData()", 
				status, status != PRO_TK_NO_ERROR);
  status = ProMenubuttonActionSet((char*)"TkGenData",(char*)"TkGenData", 
      (ProMenubuttonAction)ProMenuDelete, model, 0);
  TEST_CALL_REPORT("ProMenubuttonActionSet()", "ProTestGeneData()", 
				status, status != PRO_TK_NO_ERROR);
 
  status = ProMenuCreate(PROMENUTYPE_MAIN,(char*)"TkGenData", &id);
  TEST_CALL_REPORT("ProMenuCreate()", "ProTestGeneData()", 
				status, status != PRO_TK_NO_ERROR);
  status = ProMenuProcess((char*)"TkGenData", &id);
  TEST_CALL_REPORT("ProMenuProcess()", "ProTestGeneData()", 
				status, status != PRO_TK_NO_ERROR);

  return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
  Function : ProTestRegClass
  Purpose  : Register class
\*====================================================================*/
int ProTestRegClass(
	ProMdl p_model)
{
    ProExtdataErr    err;
    ProExtdataClass  data_class;
    ProName 	     class_name;

/*-------------------------------------------------------------*\
     Get the class name.
\*-------------------------------------------------------------*/
    ProUtilMsgPrint("gendata","TEST Enter class name [QUIT] : ");
    if(ProMessageStringRead(PRO_NAME_SIZE, class_name))
    {
        return(PRO_TK_BAD_INPUTS);
    }

/*-------------------------------------------------------------*\   
     Register the class.
\*-------------------------------------------------------------*/

    err = ProExtdataClassRegister(p_model, class_name, &data_class);
    TEST_CALL_REPORT("ProExtdataClassRegister()", "ProTestRegClass()",
                                (ProError)err, err != PROEXTDATA_TK_NO_ERROR);

    if(err != PROEXTDATA_TK_NO_ERROR)
    {
	ProUtilMsgPrint("gendata", "TEST ProExtdataClassRegister() status: %0s", 
			ProTestProAppdataErr(err));
        return(PRO_TK_GENERAL_ERROR);
    }

    ProUtilMsgPrint("gendata","TEST Class %0ws registered successfully", class_name);
    return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
  Function : ProTestSelectSlot
  Purpose  : Select a slot 
\*====================================================================*/
static int ProTestSelectSlot(
	ProExtdataClass *data_class,
	int 		*keyby,
	ProExtdataSlot  *data_slot)
{
    ProExtdataErr 	err;
    int			num_of_slots, i, n_sel;
    ProExtdataNamesList slot_name_list;
    ProExtdataIdsList	slot_id_list;
    wchar_t 		**selected, wtitle[10];
    char		tmp_str[PRO_NAME_SIZE];
    wchar_t             *list[MAX_SLOT_CLASS_NUM];
    wchar_t             empty_buff[2];
    ProError		status;

/*-------------------------------------------------------------*\
       get the name list.
\*-------------------------------------------------------------*/
    err = ProExtdataSlotNamesList(data_class, &num_of_slots,
        &slot_name_list);

    TEST_CALL_REPORT("ProExtdataSlotNamesList()", "ProTestSelectSlot()",
                                (ProError)err, err != PROEXTDATA_TK_NO_ERROR);

    if( err != PROEXTDATA_TK_NO_ERROR)
    {
        ProUtilMsgPrint("gendata","TEST ProExtdataSlotNamesList() status : %0s",
				ProTestProAppdataErr(err));
        return(0);
    }

/*-------------------------------------------------------------*\
       get the id list.
\*-------------------------------------------------------------*/
    err = ProExtdataSlotIdsList(data_class, &num_of_slots, &slot_id_list);

    TEST_CALL_REPORT("ProExtdataSlotIdsList()", "ProTestSelectSlot()",
                                (ProError)err, err != PROEXTDATA_TK_NO_ERROR);

    if( err != PROEXTDATA_TK_NO_ERROR )
    {
        ProUtilMsgPrint("gendata","TEST ProExtdataSlotIdsList() status : %0s",
				ProTestProAppdataErr(err));
        return(0);
    }

    if(num_of_slots < 1)
    {
        ProUtilMsgPrint("gendata","TEST There are no slots in class %0ws",
						data_class->class_name);
        return(0);
    }

    ProStringToWstring(empty_buff, (char*)"");
    ProUtilMsgPrint("gendata","TEST Select slot");
    ProStringToWstring(wtitle,(char*)"Slots");
    for(i = 0;i < num_of_slots; i ++)
    {
        list[i] = (wchar_t *)slot_name_list[i];
    }
    list[i] = empty_buff;

    status = ProMenuStringsSelect(wtitle,list,1,NULL,&selected, &n_sel);
    TEST_CALL_REPORT ("ProMenuStringSelect", "ProTestSelectSlot",
        status, status != PRO_TK_NO_ERROR);

    data_slot->p_class = data_class;
    ProUtilWstrcpy(data_slot->slot_name, (wchar_t *)selected[0]);
    for(i = 0;i < num_of_slots;i ++)
    {
       if(ProUtilWstrCmp(slot_name_list[i], data_slot->slot_name) == 0)
       {
           data_slot->slot_id = slot_id_list[i];
           break;
       }
    }
    ProArrayFree((ProArray *)&slot_name_list);
    ProArrayFree((ProArray *)&slot_id_list);
     
    ProWstringToString(tmp_str, data_slot->slot_name);
    if(isdigit(tmp_str[0]))
    {
        *keyby = KEY_BY_ID;
        ProStringToWstring(data_slot->slot_name, (char*)" ");
    }
    else
    {
        *keyby = KEY_BY_NAME;
    }
    return(1);   
}

/*====================================================================*\
  Function : ProTestSelectClass
  Purpose  : Select a class
\*====================================================================*/    
static int ProTestSelectClass(
	ProMdl p_model, 
	ProExtdataClass *p_class)
{
    ProExtdataErr    	err;
    ProName	        *class_name_list;
    int			num_of_class, n_sel, i;
    wchar_t		wtitle[10];
    wchar_t		**selected;
    wchar_t             *list[MAX_SLOT_CLASS_NUM];
    wchar_t             empty_buff[2];		
    ProError		status;

/*-------------------------------------------------------------*\
     Get the class list
\*-------------------------------------------------------------*/
    err=ProExtdataClassNamesList(p_model, &num_of_class, &class_name_list);

    TEST_CALL_REPORT("ProExtdataClassNamesList()", "ProTestSelectClass()",
                                (ProError)err, err != PROEXTDATA_TK_NO_ERROR);

    if( err != PROEXTDATA_TK_NO_ERROR )
    {
        ProUtilMsgPrint("gendata","TEST ProExtdataClassNamesList() status : %0s",
                                		ProTestProAppdataErr(err));				
        return(0);
    }
    
    if(num_of_class < 1)
    {
	ProUtilMsgPrint("gendata","TEST There are no classes defined");
        return(0);
    }
    
    ProStringToWstring(empty_buff, (char*)""); 
    ProUtilMsgPrint("gendata","TEST Select class");
    ProStringToWstring(wtitle,(char*)"Classes");

    for(i = 0;i < num_of_class; i ++)
    {
        list[i] = (wchar_t *)class_name_list[i];
    }
    list[i] = empty_buff;

    status = ProMenuStringsSelect(wtitle, list, 1, NULL, &selected, &n_sel);

    ProArrayFree((ProArray *)&class_name_list);
    if(status != PRO_TK_NO_ERROR || n_sel < 1)
    {
        return(0);
    }
  
    p_class->p_model = p_model;
    ProUtilWstrcpy(p_class->class_name, selected[0]);
    return(1);
}

/*====================================================================*\
  Function : ProTestCreateSlot
  Purpose  : Create the slot
\*====================================================================*/
int ProTestCreateSlot(
	ProMdl p_model)
{
    ProExtdataClass  data_class;
    ProName	     slot_name;
    ProExtdataSlot   data_slot;
    ProExtdataErr    err;
 
/*-------------------------------------------------------------*\
    Select a class name for the slot to belong to
\*-------------------------------------------------------------*/
    if(ProTestSelectClass(p_model, &data_class) == 0)
        return(PRO_TK_BAD_INPUTS);
 
/*-------------------------------------------------------------*\
    Get the slot name
\*-------------------------------------------------------------*/
    ProUtilMsgPrint("gendata","TEST Enter slot name [NONE] : ");
 
/*-------------------------------------------------------------*\
    If no slot name was given, then create one with no name
    (i.e. we will KEY_BY_ID)
    else use the name.
\*-------------------------------------------------------------*/
    if(!ProMessageStringRead(PRO_NAME_SIZE, slot_name))
    {
        err = ProExtdataSlotCreate(&data_class, slot_name, &data_slot);
    }
    else
    {
        err = ProExtdataSlotCreate(&data_class, NULL, &data_slot);
    }

    TEST_CALL_REPORT("ProExtdataSlotCreate()", "ProTestCreateSlot()",
                                (ProError)err, err != PROEXTDATA_TK_NO_ERROR);

    if(err == PROEXTDATA_TK_NO_ERROR)
    { 
        ProUtilMsgPrint("gendata","TEST Created slot with id %0d", &data_slot.slot_id);
        return(PRO_TK_NO_ERROR);
    }
    ProUtilMsgPrint("gendata","TEST ProExtdataSlotCreate() status : %0s",
                        ProTestProAppdataErr(err));
 
    return(PRO_TK_GENERAL_ERROR);
}

/*====================================================================*\
  Function : ProTestUserAction
  Purpose  : exit the data type menu 
\*====================================================================*/
static int ProTestUserAction(
	char *dummy,
	int action)
{
    ProError err;
    err = ProMenuDeleteWithStatus(action);
    TEST_CALL_REPORT ("ProMenuDeleteWithStatus","ProTestUserAction", err,
        err != PRO_TK_NO_ERROR);

    return 0;
}

/*====================================================================*\
  Function : ProTestGetDataType
  Purpose  : Create the data type menu
\*====================================================================*/
static int ProTestGetDataType()
{
    ProError	status;
    int id;

    status = ProMenuFileRegister((char*)"TkGenType",(char*)"tkgentype.mnu", &id);
    TEST_CALL_REPORT ("ProMenuFileRegister", "ProTestGetDataType", status,
        status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet((char*)"TkGenType",(char*)"-Integer",
        (ProMenubuttonAction)ProTestUserAction, NULL,PRO_INTEGER_TYPE);
    TEST_CALL_REPORT("ProMenubuttonActionSet()", "ProTestGetDataType()", 
				status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet((char*)"TkGenType",(char*)"-Double",
        (ProMenubuttonAction)ProTestUserAction, NULL,PRO_DOUBLE_TYPE);
    TEST_CALL_REPORT("ProMenubuttonActionSet()", "ProTestGetDataType()", 
				status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet((char*)"TkGenType",(char*)"-Wide Str",
        (ProMenubuttonAction)ProTestUserAction,	NULL,PRO_WIDE_STRING_TYPE);
    TEST_CALL_REPORT("ProMenubuttonActionSet()", "ProTestGetDataType()", 
				status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet((char*)"TkGenType",(char*)"-Stream",
        (ProMenubuttonAction)ProTestUserAction, NULL,PRO_STREAM_TYPE);
    TEST_CALL_REPORT("ProMenubuttonActionSet()", "ProTestGetDataType()", 
				status, status != PRO_TK_NO_ERROR);
    status = ProMenubuttonActionSet((char*)"TkGenType",(char*)"TkGenType",
        (ProMenubuttonAction)ProTestUserAction,NULL,-1);
    TEST_CALL_REPORT("ProMenubuttonActionSet()", "ProTestGetDataType()", 
				status, status != PRO_TK_NO_ERROR);  
    ProUtilMsgPrint("gendata","TEST Select data type");

    status = ProMenuCreate(PROMENUTYPE_MAIN,(char*)"TkGenType", &id);
    TEST_CALL_REPORT("ProMenuCreate()", "ProTestGetDataType()", 
				status, status != PRO_TK_NO_ERROR);

    status = ProMenuProcess((char*)"TkGenType", &id);
    if (status == PRO_TK_NO_ERROR)
	return (id);
    else
    	return(-1);
}

/*====================================================================*\
  Function : ProTestHexToByte
  Purpose  : Convert hex to str
\*====================================================================*/
static unsigned char ProTestHexToByte(
	char *str)
{
    int i;
    char h;
    unsigned char b;
 
    b=0;
    for(i=0;i<2;i++)
    {
        h = (char)toupper(str[i]);
        if(isdigit(h))
            b = (unsigned char)(b*16 + (int)(h - '0'));
        else
            b = (unsigned char)(b*16 + (int)(h - 'A') + 10);
    }
    return(b);
}

/*====================================================================*\
  Function : ProTestWrCheck
  Purpose  : Check the data slot write and read back functions
\*====================================================================*/
int ProTestWrCheck(
	ProMdl p_model)
{
   ProExtdataErr  	err;
   int 			data_type, keyby, i, i_read, b, differ, data_size;
   ProExtdataClass 	data_class;
   ProExtdataSlot  	data_slot;
   unsigned char 	*stream,*s_read;	
   double 		d,d_read;
   void 		*data;
   char 		str[PRO_LINE_SIZE];
   wchar_t 		wstr[PRO_LINE_SIZE];
   int			cont = 1;

/*-------------------------------------------------------------*\
    Get the type of slot (integer, double etc.)
\*-------------------------------------------------------------*/
    data_type = ProTestGetDataType();
    if(data_type < 0)
    {
        return(PRO_TK_BAD_INPUTS);
    }

/*-------------------------------------------------------------*\
    Get the class
\*-------------------------------------------------------------*/
   if(!ProTestSelectClass(p_model, &data_class))
   {
       return(PRO_TK_BAD_INPUTS);
   }

/*-------------------------------------------------------------*\
    Get the slot
\*-------------------------------------------------------------*/
   if(!ProTestSelectSlot(&data_class, &keyby, &data_slot))
   {
      return(PRO_TK_BAD_INPUTS);
   }

ProTKPrintf("%d\n", data_type);
/*-------------------------------------------------------------*\
    Depending upon the type of data, get the user to type the
    data, and then save it to the slot.
\*-------------------------------------------------------------*/
    switch(data_type)
    {
    case PRO_INTEGER_TYPE :

        ProUtilMsgPrint("gendata","TEST Enter integer [QUIT] : ");
        if(ProMessageIntegerRead(NULL, &i))
            return(PRO_TK_BAD_INPUTS);
        err = ProExtdataSlotWrite(&data_slot, keyby, PRO_INTEGER_TYPE, 0, &i);
        break;
    case PRO_DOUBLE_TYPE :
        ProUtilMsgPrint("gendata","TEST Enter double [QUIT] : ");
        if(ProMessageDoubleRead(NULL, &d))
            return(PRO_TK_BAD_INPUTS);
        err = ProExtdataSlotWrite(&data_slot, keyby, PRO_DOUBLE_TYPE, 0, &d);
        break;
    case PRO_WIDE_STRING_TYPE :
        ProUtilMsgPrint("gendata","TEST Enter string [QUIT] : ");
        if(ProMessageStringRead(PRO_LINE_SIZE, wstr))
            return(PRO_TK_BAD_INPUTS);
        err = ProExtdataSlotWrite(&data_slot, keyby, PRO_WIDE_STRING_TYPE, 
								0, wstr);
        break;
    case PRO_STREAM_TYPE :
        b=0;
        do 
        {
            ProUtilMsgPrint("gendata","TEST Enter bytes in hexadecimal [QUIT] : ");
            if(ProMessageStringRead(PRO_LINE_SIZE, wstr))
                break;
            ProWstringToString(str,wstr);
            if(strlen(str)%2)
                str[strlen(str)-1] = '\0';
            if(b==0)
                stream = (unsigned char*)calloc(strlen(str)/2,1);
            else
                stream = (unsigned char*)realloc(stream, b + strlen(str)/2);
            for(i=0;i<(int)strlen(str);i+=2)
                stream[b++] = ProTestHexToByte(&str[i]);
        } while (cont);
        err = ProExtdataSlotWrite(&data_slot, keyby, PRO_STREAM_TYPE, b,stream);
        break;
    }
    
    TEST_CALL_REPORT("ProExtdataSlotWrite()", "ProTestWrCheck()",
                                (ProError)err, err != PROEXTDATA_TK_NO_ERROR);

    if(err)
    {
        ProUtilMsgPrint("gendata","TEST ProExtdataSlotWrite() status : %0s",
                        ProTestProAppdataErr(err));
        return(PRO_TK_GENERAL_ERROR);
    }

/*-------------------------------------------------------------*\
    Read back the data, and compare its value
\*-------------------------------------------------------------*/
    err = ProExtdataSlotRead(&data_slot, keyby, &data_type, &data_size, &data);
 
    TEST_CALL_REPORT("ProExtdataSlotRead()", "ProTestWrCheck()",
                                (ProError)err, err != PROEXTDATA_TK_NO_ERROR);

    if(err)
    {
        ProUtilMsgPrint("gendata","TEST ProExtdataSlotRead() status : %0s",
                        ProTestProAppdataErr(err));
        return(0);
    }
    switch(data_type)
    {
    case PRO_INTEGER_TYPE :
        i_read = *(int*)data;
        if(i_read != i)
            ProUtilMsgPrint("gendata","TEST INCORRECT value read back = %0d",
                                                                    &i_read);
        else
            ProUtilMsgPrint("gendata","TEST Value read back = %0d",&i_read);
        break;
    case PRO_DOUBLE_TYPE :
        d_read = *(double*)data;
        if(fabs(d_read - d) > 0.0000001)
            ProUtilMsgPrint("gendata","TEST INCORRECT value read back = %0f",
                                                                &d_read);
        else
            ProUtilMsgPrint("gendata","TEST Value read back = %0f",&d_read);
        break;
    case PRO_WIDE_STRING_TYPE :
        if(ProUtilWstrCmp((wchar_t*)data, wstr))
            ProUtilMsgPrint("gendata","TEST INCORRECT value read back = %0w",
                                                            (wchar_t*)data);
        else
            ProUtilMsgPrint("gendata","TEST Value read back = %0w",(wchar_t*)data);
        break;
    case PRO_STREAM_TYPE :
        s_read = (unsigned char*)data;
        differ=0;
        for(b=0;b<data_size;b++)
            if(s_read[b] != stream[b])
            {
                differ=1;
                break;
            }
        if(differ)
            ProUtilMsgPrint("gendata","TEST INCORRECT value read back");
        else
            ProUtilMsgPrint("gendata","TEST Correct value read back");
        break;
    }
    err = ProExtdataFree(&data);
    TEST_CALL_REPORT("ProExtdataFree()", "ProTestWrCheck()",
                                (ProError)err, err != PROEXTDATA_TK_NO_ERROR);

    return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
  Function : ProTestRandom
  Purpose  : Random data access to data slots
\*====================================================================*/
int ProTestRandom(
	ProMdl p_model)
{
    ProName          class_name;
    ProExtdataErr    err;
    ProExtdataClass  data_class;
    int              data_size;

/*-------------------------------------------------------------*\
    Get the new class name
\*-------------------------------------------------------------*/
    ProUtilMsgPrint("gendata","TEST Enter class name [QUIT] : ");
    if(ProMessageStringRead(PRO_NAME_SIZE, class_name))
        return(PRO_TK_BAD_INPUTS);
 
/*-------------------------------------------------------------*\
    Register it
\*-------------------------------------------------------------*/
    err = ProExtdataClassRegister(p_model, class_name, &data_class);
    
    TEST_CALL_REPORT("ProExtdataClassRegister()", "ProTestRandom( )",
                                (ProError)err, (ProError)err != PRO_TK_NO_ERROR);

    if(err != PROEXTDATA_TK_NO_ERROR)
    {
        ProUtilMsgPrint("gendata","TEST ProExtdataClassRegister() %0s",
                                        ProTestProAppdataErr(err));
        return(PRO_TK_GENERAL_ERROR);
    }
 
/*-------------------------------------------------------------*\
    Get how many bytes of data to generate
\*-------------------------------------------------------------*/
    ProUtilMsgPrint("gendata","TEST Enter number of bytes to save [QUIT] : ");
    if(ProMessageIntegerRead(NULL, &data_size))
        return(PRO_TK_BAD_INPUTS);
 
/*-------------------------------------------------------------*\
    Generate and save the data
\*-------------------------------------------------------------*/
    /* create func to replace user_save_random_data() .*/

    ProTestSvRdmData(&data_class, data_size); 
    return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
  Function : ProTestDump
  Purpose  : Dump all the generic data to a file
\*====================================================================*/
int ProTestDump(
	ProMdl p_model)
{
    FILE 		*fp;
    char 		fname[40], tmp_str[PRO_NAME_SIZE];
    wchar_t 		w_fname[40];
    ProExtdataNamesList	class_name_list;
    ProExtdataNamesList	slot_name_list;
    ProExtdataIdsList	slot_id_list;
    ProExtdataErr	err;
    int			num_of_class, num_of_slots, c, s, b, keyby;
    int			data_type, data_size;
    void 		*data;
    char 		str[256];
    ProExtdataClass	data_class;
    ProExtdataSlot	data_slot;
    unsigned char 	*stream;

    fp = ProUtilGenFilePtr(p_model, (char*)GENERIC, (char*)fname, (char*)"w");


    err=ProExtdataClassNamesList(p_model, &num_of_class, &class_name_list);
 
    TEST_CALL_REPORT("ProExtdataClassNamesList()", "ProTestDump()",
                                (ProError)err, err != PROEXTDATA_TK_NO_ERROR);

    if (err != PROEXTDATA_TK_NO_ERROR )
    {
        ProUtilMsgPrint("gendata","TEST ProExtdataClassNamesList() status : %0s",
                                                ProTestProAppdataErr(err));
 
        return(PRO_TK_GENERAL_ERROR);
    } 

    if(num_of_class < 1)
    {
        ProUtilMsgPrint("gendata","TEST No generic data present");
        return(PRO_TK_GENERAL_ERROR);
    }
    data_class.p_model = p_model;
    for(c=0;c<num_of_class;c++)
    {
        ProWstringToString(tmp_str, class_name_list[c]);
        ProTKFprintf(fp,"CLASS %s\n", tmp_str);
        ProUtilWstrcpy(data_class.class_name, class_name_list[c]);

        err = ProExtdataSlotNamesList(&data_class, &num_of_slots, 
						&slot_name_list);
 
        TEST_CALL_REPORT("ProExtdataSlotNamesList()", "ProTestDump()",
                                (ProError)err, err != PROEXTDATA_TK_NO_ERROR);

        if(num_of_slots <1)
        {
           ProTKFprintf(fp,"    (NO SLOTS)\n");
            continue;
        }

        err = ProExtdataSlotIdsList(&data_class, &num_of_slots, &slot_id_list);
        
        TEST_CALL_REPORT("ProExtdataSlotIdsList()", "ProTestDump()",
                                (ProError)err, err != PROEXTDATA_TK_NO_ERROR);

        data_slot.p_class = &data_class;
        
        ProTKFprintf(fp,"    SLOTS..\n");
        for(s=0;s<num_of_slots;s++)
        {
            ProTKFprintf(fp,"    %d :\n",slot_id_list[s]);
            data_slot.slot_id = slot_id_list[s];
  	    ProUtilWstrcpy(data_slot.slot_name, slot_name_list[s]);

            keyby = KEY_BY_NAME;
            ProWstringToString(tmp_str, slot_name_list[s]);
            if(strlen(tmp_str) == 0 ||
               isdigit(tmp_str[0]))
                keyby = KEY_BY_ID;
 
            err = ProExtdataSlotRead(&data_slot, keyby, &data_type, 
						&data_size, &data);

            TEST_CALL_REPORT("ProExtdataSlotRead()", "ProTestDump()",
                                (ProError)err, err != PROEXTDATA_TK_NO_ERROR);

            if(err != PROEXTDATA_TK_NO_ERROR)
            {
                ProTKFprintf(fp,"        NO VALUE READ\n");
                continue;
            }

            switch(data_type)
            {
            case PRO_INTEGER_TYPE :
                ProTKFprintf(fp,"        INTEGER = %d\n",*(int*)data);
                break;
            case PRO_DOUBLE_TYPE :
                ProTKFprintf(fp,"        DOUBLE  = %f\n",*(double*)data);
                break;
            case PRO_WIDE_STRING_TYPE :
                ProTKFprintf(fp,"        STRING  = %s\n",
                        ProWstringToString(str,(wchar_t*)data));
                break;
            case PRO_STREAM_TYPE :
                stream = (unsigned char *)data;
                ProTKFprintf(fp,"        STREAM  = ");
                for(b=0;b<data_size;b++)
                {
                    ProTKFprintf(fp,"%02x",stream[b]);
                    if((b+1)%100 == 0)
                        ProTKFprintf(fp,"\n             ");
                }
                ProTKFprintf(fp,"\n");
                break;
            }
    	    err = ProExtdataFree(&data);
    	    TEST_CALL_REPORT("ProExtdataFree()", "ProTestDump()",
                                (ProError)err, err != PROEXTDATA_TK_NO_ERROR);

        }
    }
    fclose(fp);

    ProArrayFree((ProArray *)&class_name_list);
    ProArrayFree((ProArray *)&slot_name_list);
    ProArrayFree((ProArray *)&slot_id_list);
    
    ProStringToWstring(w_fname, fname);
    ProInfoWindowDisplay(w_fname, NULL, NULL);
    return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
  Function : ProTestDeleteC
  Purpose  : Delete the selected class
\*====================================================================*/
int ProTestDeleteC(
	ProMdl p_model)
{
    ProExtdataClass     data_class;
    ProExtdataErr       err;

    if(!ProTestSelectClass(p_model, &data_class))
        return(PRO_TK_BAD_INPUTS);

    err = ProExtdataClassUnregister(&data_class);
    TEST_CALL_REPORT("ProExtdataClassUnregister()", "ProTestDeleteC()",
                                (ProError)err, err != PROEXTDATA_TK_NO_ERROR);

    if(err != PROEXTDATA_TK_NO_ERROR)
    {
        ProUtilMsgPrint("gendata","TEST ProExtdataClassUnregister() status : %0s",
                                        ProTestProAppdataErr(err));
        return(PRO_TK_GENERAL_ERROR);
    }

    return(PRO_TK_NO_ERROR);
}


/*====================================================================*\
  Function : ProTestDelete
  Purpose  : Delete the selected slot
\*====================================================================*/
int ProTestDelete(
        ProMdl p_model)
{
    ProExtdataClass     data_class;
    ProExtdataSlot      data_slot;
    int			keyby;
    ProExtdataErr       err;

    if(!ProTestSelectClass(p_model, &data_class))
        return(PRO_TK_BAD_INPUTS);
 
    if(!ProTestSelectSlot(&data_class, &keyby, &data_slot))
        return(PRO_TK_BAD_INPUTS);
 
    err = ProExtdataSlotDelete(&data_slot, keyby);

    TEST_CALL_REPORT("ProExtdataSlotDelete()", "ProTestDelete()",
                                (ProError)err, err != PROEXTDATA_TK_NO_ERROR);

    if(err != PROEXTDATA_TK_NO_ERROR)
    {
        ProUtilMsgPrint("gendata","TEST ProExtdataSlotDelete() status : %0s",
                                        ProTestProAppdataErr(err));
        return(PRO_TK_GENERAL_ERROR);
    }

    return(PRO_TK_NO_ERROR);
}

/*====================================================================*\
  Function : ProTestRefresh
  Purpose  : Reload the generic data from the file.
\*====================================================================*/
int ProTestRefresh(
 	ProMdl p_model)	
{
    ProExtdataErr err;

    err = ProExtdataTerm(p_model);

    TEST_CALL_REPORT("ProExtdataTerm()", "ProTestRefresh()",
                                (ProError)err, err != PROEXTDATA_TK_NO_ERROR);
    
    if(err != PROEXTDATA_TK_NO_ERROR)
    {
        ProUtilMsgPrint("gendata","TEST ProExtdataTerm() status : %0s",
                                        ProTestProAppdataErr(err));
        return(PRO_TK_GENERAL_ERROR);
    }
   
    err = ProExtdataInit(p_model);

    TEST_CALL_REPORT("ProExtdataInit()", "ProTestRefresh()",
                                (ProError)err, err != PROEXTDATA_TK_NO_ERROR);

    if(err != PROEXTDATA_TK_NO_ERROR)
    {
        ProUtilMsgPrint("gendata","TEST ProExtdataInit() status : %0s",
                                        ProTestProAppdataErr(err));
        return(PRO_TK_GENERAL_ERROR);
    }

    err = ProExtdataLoadAll(p_model);

    TEST_CALL_REPORT("ProExtdataLoadAll()", "ProTestRefresh()",
                                (ProError)err, err != PROEXTDATA_TK_NO_ERROR);
 
    if(err != PROEXTDATA_TK_NO_ERROR)
    {
        ProUtilMsgPrint("gendata","TEST ProExtdataLoadAll() status : %0s",
                                        ProTestProAppdataErr(err));
        return(PRO_TK_GENERAL_ERROR);
    }

    return(PRO_TK_NO_ERROR);
}