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


/*--------------------------------------------------------------------*\
Pro/Toolkit includes -- include this first
\*--------------------------------------------------------------------*/
#include "ProToolkit.h"
#include "ProMdl.h"
#include "ProMenu.h"
#include "ProMessage.h"
#include "ProRelSet.h"
#include "ProModelitem.h"
#include "ProSelection.h"
#include <ProTKRunTime.h>
#include <PTApplsUnicodeUtils.h>
#include <ProUtil.h>
#include <UtilFiles.h>

/*--------------------------------------------------------------------*\
Pro/Develop includes
\*--------------------------------------------------------------------*/

/*--------------------------------------------------------------------*\
Application includes
\*--------------------------------------------------------------------*/
#include "TestError.h"
#include "TestSetup.h"
#include "UtilMessage.h"
#include "UtilString.h"
#include "TestFiletypes.h"
#include "UtilTypes.h"
#include "UtilCollect.h"
/*--------------------------------------------------------------------*\
Application macros
\*--------------------------------------------------------------------*/

#define USER_RL_EDIT  0 
#define USER_RL_DELETE 1

/*====================================================================*\
FUNCTION : ProTestRelationsMenu
PURPOSE  : Top level menu for the Relations Menu testing.
\*====================================================================*/
int ProTestRelationsMenu(ProMdl *model)
{
  ProMdlType   model_type;
  int          action;
  ProError     status;

    int ProTestModelRelsMenu();
    int ProTestModelRelsetInfo();

    status = ProMdlTypeGet(*model, &model_type);
    TEST_CALL_REPORT("ProMdlTypeGet()", "ProTestRelationsMnu()", status,
						status != PRO_TK_NO_ERROR);
    ProMenuPush();
    ProMenuFileRegister((char*)"TkModelRel",(char*)"tkmodelrel.mnu", NULL);
    ProMenubuttonActionSet((char*)"TkModelRel",(char*)"TkModelRel",
                           (ProMenubuttonAction)ProMenuDelete, NULL,  0);
    ProMenubuttonActionSet((char*)"TkModelRel",(char*)"-Done",
                           (ProMenubuttonAction)ProMenuDelete, NULL,  0);
    ProMenubuttonActionSet((char*)"TkModelRel",(char*)"-Assem Rel",
                           (ProMenubuttonAction)ProTestModelRelsMenu,
                                               model, PRO_RELOBJ_ASSEMBLY);
    ProMenubuttonActionSet((char*)"TkModelRel",(char*)"-Part Rel",
                           (ProMenubuttonAction)ProTestModelRelsMenu,
                                               model, PRO_RELOBJ_PART);
    ProMenubuttonActionSet((char*)"TkModelRel",(char*)"-Feat Rel",
                           (ProMenubuttonAction)ProTestModelRelsMenu,
                                               model, PRO_RELOBJ_FEATURE);
    ProMenubuttonActionSet((char*)"TkModelRel",(char*)"-Surface Rel",
                           (ProMenubuttonAction)ProTestModelRelsMenu,
                                               model, PRO_RELOBJ_SURFACE);
    ProMenubuttonActionSet((char*)"TkModelRel",(char*)"-Edge Rel",
                           (ProMenubuttonAction)ProTestModelRelsMenu,
                                               model, PRO_RELOBJ_EDGE);
    ProMenubuttonActionSet((char*)"TkModelRel",(char*)"-Info",
        (ProMenubuttonAction)ProTestModelRelsetInfo, model, 0);
    ProMenuCreate(PROMENUTYPE_MAIN, (char*)"TkModelRel", NULL);
    if ( model_type == PRO_MDL_ASSEMBLY)
        ProMenubuttonActivate((char*)"TkModelRel",(char*)"-Assem Rel");
    else
        ProMenubuttonDeactivate((char*)"TkModelRel",(char*)"-Assem Rel");

    ProMenuProcess((char*)"", &action);
    ProMenuPop();

  return(0);
}


/*====================================================================*\
    FUNCTION :	ProTestModelRelsMenu()
    PURPOSE  :  General action function for the Note testing.
\*====================================================================*/
int ProTestModelRelsMenu(
    ProMdl *model,
    int action)
{
  ProError status;
  ProMdlType   model_type;
  ProModelitem modelitem;
  int select = 0, n_sel;
  char *opt = NULL;
  ProSelection *p_sel;
  ProCharLine str;
  ProName w_name;

  int ProTestAddModelitemRel();
  int ProTestEditModelitemRel();
  int ProTestRegenerateModelitemRel();

    status = ProMdlTypeGet(*model, &model_type);
    TEST_CALL_REPORT("ProMdlTypeGet()", "ProTestModelRelsMenu()", status,
						status != PRO_TK_NO_ERROR);

    if (((action == PRO_RELOBJ_PART) && ( model_type == PRO_MDL_PART)) ||
	(action == PRO_RELOBJ_ASSEMBLY))
    {
	status = ProMdlToModelitem(*model, &modelitem);
	TEST_CALL_REPORT("ProMdlToModelitem()", "ProTestModelRelsMenu()", 
	    status, status != PRO_TK_NO_ERROR);
	select = 1;
    }
    else
    {
    	switch(action)
    	{
	case PRO_RELOBJ_PART :
	    opt = (char*)"part";
            break;
    	case PRO_RELOBJ_FEATURE :
	    opt = (char*)"feature";
       	    break;
        case PRO_RELOBJ_SURFACE :
	    opt = (char*)"surface";
            break;
        case PRO_RELOBJ_EDGE :
	    opt = (char*)"edge";
            break;
        case PRO_RELOBJ_PAT_DIR1 :
            break;
	}

	if (opt != NULL)
	{
	    ProTKSprintf(str, (char*)"Select %s", opt);
    	    ProUtilMsgPrint((char*)"gen", (char*)"TEST %0s", str);

	    status = ProSelect(opt, 1, NULL, NULL, NULL, NULL, &p_sel, &n_sel);
	    if (status == PRO_TK_NO_ERROR && n_sel == 1)
	    {
		status = ProSelectionModelitemGet(p_sel[0], &modelitem);
	        TEST_CALL_REPORT("ProSelectionModelitemGet()", 
		    "ProTestModelRelsMenu()", status, 
		    status != PRO_TK_NO_ERROR);
		
		if (modelitem.type==PRO_EDGE || modelitem.type==PRO_SURFACE)
		{
/*--------------------------------------------------------------------------*\
   Only named edges and surfaces can have relations 
\*--------------------------------------------------------------------------*/
		    status = ProModelitemNameGet(&modelitem, w_name);
	            TEST_CALL_REPORT("ProModelitemNameGet()", 
		    	"ProTestModelRelsMenu()", status, 
			status != PRO_TK_NO_ERROR);

		    if (status != PRO_TK_NO_ERROR)
		    {
			ProTKSprintf(str, (char*)"Please name selected %s first [-QUIT-]:",
			    opt);
    	    		ProUtilMsgPrint((char*)"gen", (char*)"TEST %0s", str);

			status = ProMessageStringRead(PRO_NAME_SIZE, w_name);
	            	TEST_CALL_REPORT("ProMessageStringRead()", 
		    	    "ProTestModelRelsMenu()", status, 
			     status != PRO_TK_NO_ERROR);
			
			if (status == PRO_TK_NO_ERROR)
			{
			    status = ProModelitemNameSet(&modelitem, w_name);
	            	    TEST_CALL_REPORT("ProModelitemNameSet()", 
		    	    	"ProTestModelRelsMenu()", status, 
			     	status != PRO_TK_NO_ERROR);

			    if (status == PRO_TK_NO_ERROR)
				select = 1;				
			}
		    }
		}
		else
		    select = 1;
	    }
        }
    }

    ProMenuFileRegister((char*)"TkRelations",(char*)"tkrelations.mnu", NULL);
    ProMenubuttonActionSet((char*)"TkRelations",(char*)"TkRelations",
                           (ProMenubuttonAction)ProMenuDelete, NULL,  0);
    ProMenubuttonActionSet((char*)"TkRelations",(char*)"-Add Rel",
        (ProMenubuttonAction)ProTestAddModelitemRel, &modelitem, 0);
    ProMenubuttonActionSet((char*)"TkRelations",(char*)"-Edit Rel",
        (ProMenubuttonAction)ProTestEditModelitemRel, &modelitem, USER_RL_EDIT);
    ProMenubuttonActionSet((char*)"TkRelations",(char*)"-Delete Rel",
        (ProMenubuttonAction)ProTestEditModelitemRel, &modelitem, 
	USER_RL_DELETE);
    ProMenubuttonActionSet((char*)"TkRelations",(char*)"-Regenerate",
        (ProMenubuttonAction)ProTestRegenerateModelitemRel, &modelitem, 0);
    ProMenubuttonActionSet((char*)"TkRelations",(char*)"-Done/Return",
        (ProMenubuttonAction)ProMenuDelete, NULL, 0);

    ProMenuCreate(PROMENUTYPE_MAIN, (char*)"TkRelations", NULL);
    ProMenuProcess((char*)"", &action);

  return(0);
}


/*====================================================================*\
    FUNCTION :	ProTestAddModelitemRel()
    PURPOSE  :  Add new relation to the modelitem
\*====================================================================*/
int ProTestAddModelitemRel(
    ProModelitem *modelitem)
{
  ProError status;
  ProLine w_line;
  ProWstring *w_array;
  int n_lines, cont=1;
  ProRelset relset;
  wchar_t *w_ptr;

    while (cont)
    {
    ProUtilMsgPrint((char*)"gen", (char*)"TEST %0s", (char*)"Enter Relation [QUIT]:");

    status = ProMessageStringRead(PRO_LINE_SIZE, w_line);
    if (status == PRO_TK_NO_ERROR)
    {   
	status = ProArrayAlloc(0, sizeof(ProWstring), 1, (ProArray*)&w_array);
	TEST_CALL_REPORT("ProArrayAlloc()", "ProTestAddModelitemRel()", 
					status, status != PRO_TK_NO_ERROR);
                                        
	status = ProModelitemToRelset(modelitem, &relset);
	TEST_CALL_REPORT("ProModelitemToRelset()", "ProTestAddModelitemRel()", 
	    status, status != PRO_TK_NO_ERROR && status != PRO_TK_E_NOT_FOUND);
	
	if (status == PRO_TK_NO_ERROR)
	{
	    status = ProRelsetRelationsGet(&relset, &w_array);
	    TEST_CALL_REPORT("ProRelsetRelationsGet()", 
		"ProTestAddModelitemRel()", status, (status != PRO_TK_NO_ERROR)&&
                        (status!=PRO_TK_BAD_INPUTS));
	}
	else
	{
	    status = ProRelsetCreate(modelitem, &relset);
	    TEST_CALL_REPORT("ProRelsetCreate()", 
		"ProTestAddModelitemRel()", status, status != PRO_TK_NO_ERROR);
	}
	w_ptr = w_line;
	status = ProArrayObjectAdd((ProArray*)&w_array, PRO_VALUE_UNUSED, 1,
	    &w_ptr);
	TEST_CALL_REPORT("ProArrayObjectAdd()", "ProTestAddModelitemRel()", 
					status, status != PRO_TK_NO_ERROR);
	status = ProArraySizeGet((ProArray)w_array, &n_lines);
	TEST_CALL_REPORT("ProArraySizeGet()", "ProTestAddModelitemRel()", 
					status, status != PRO_TK_NO_ERROR);
	status = ProRelsetRelationsSet(&relset, w_array, n_lines);
	TEST_CALL_REPORT("ProRelsetRelationsSet()", 
	    "ProTestAddModelitemRel()", status, status != PRO_TK_NO_ERROR);
	if (status == PRO_TK_NO_ERROR)
	    ProUtilMsgPrint((char*)"gen", (char*)"TEST %0s", (char*)"Relation added successfully");
	
	status = ProArrayFree((ProArray*)&w_array);
	TEST_CALL_REPORT("ProArrayFree()", "ProTestAddModelitemRel()", 
					status, status != PRO_TK_NO_ERROR);
    }
    else
	cont = 0;
    }
    return (0);
}

/*====================================================================*\
    FUNCTION :	ProTestEditModelitemRel()
    PURPOSE  :  Edit/Delete existing relations for the modelitem
\*====================================================================*/
int ProTestEditModelitemRel(
    ProModelitem *modelitem,
    int action)
{
  ProError status;
  ProLine w_line;
  ProCharLine str, line;
  ProWstring *w_array;
  int i, n_lines, sel_index;
  wchar_t w_empty = 0, **w_select, *w_ptr;
  ProRelset relset;
  ProName w_name;

  ProWstring *mod_w_array;
  char  m_name[PRO_VALUE_SIZE], *mod_name; 
  char cntr_line[PRO_NAME_SIZE], mod_w_array_str[PRO_NAME_SIZE];
  int *repeat_cntr, j, num_lines;


    status = ProModelitemToRelset(modelitem, &relset);
    TEST_CALL_REPORT("ProModelitemToRelset()", "ProTestEditModelitemRel()", 
	    status, status != PRO_TK_NO_ERROR && status != PRO_TK_E_NOT_FOUND);
	
    if (status != PRO_TK_NO_ERROR)
    {
    	ProUtilMsgPrint((char*)"gen", (char*)"TEST %0s", (char*)"No relations found");
	return (0);
    }

    status = ProArrayAlloc(0, sizeof(ProWstring), 1, (ProArray*)&w_array);
    TEST_CALL_REPORT("ProArrayAlloc()", "ProTestEditModelitemRel()", 
					status, status != PRO_TK_NO_ERROR);

    status = ProRelsetRelationsGet(&relset, &w_array);
    TEST_CALL_REPORT("ProRelsetRelationGet()", 
	"ProTestEditModelitemRel()", status, status != PRO_TK_NO_ERROR);


    status = ProArraySizeGet((ProArray)w_array, &n_lines);
    TEST_CALL_REPORT("ProArraySizeGet()", "ProTestEditModelitemRel()", 
					status, status != PRO_TK_NO_ERROR);

/*----------------------------------------------------------------*\
   As any individual string in wchar_t** array of strings that is passed 
   to the function ProMenuStringsSelect is restricted to PRO_NAME_SIZE-1, 
   we check if the relation strings (w_array) that is passed to this function 
   is limited to this size. So the relation strings form w_array are copied 
   to a new array called mod_w_array after each string is truncated and  
   modified to avoid duplication. 
\*-----------------------------------------------------------------*/


/*----------------------------------------------------------------*\
 Creating new Array mod_w_array of same size as w_array plus one extra
 element for the required empty string terminator. 
\*-----------------------------------------------------------------*/

    status = ProArrayAlloc ((n_lines+1) , sizeof(ProWstring), 1, (ProArray*)&mod_w_array);
    TEST_CALL_REPORT("ProArrayAlloc()", "ProTestEditModelitemRel()", 
					status, status != PRO_TK_NO_ERROR);


/*----------------------------------------------------------------*\
    repeat_cntr is created to count the num of times the truncated string in 
    mod_w_array is repeated. 
\*-----------------------------------------------------------------*/

    repeat_cntr = (int *) malloc ( sizeof (int) * n_lines); 

    for (i=0; i<n_lines; i++)
    {
	int is_same = -1; 
	repeat_cntr[i] = 0;
	ProWstringToString (m_name, w_array[i]);

	if (strlen (m_name) > (PRO_NAME_SIZE - 3))
	{
	    mod_name = (char *) malloc ( sizeof (char) * PRO_NAME_SIZE);
	    ProUtilstrncpy (mod_name, (const char*)m_name, PRO_NAME_SIZE-4);
	    mod_name[PRO_NAME_SIZE-4] = '\0';
	}
	else
	{
	    mod_name = (char *) malloc ( sizeof (char) * (strlen (m_name)+1));
	    ProUtilstrcpy (mod_name, (const char*)m_name);
	}

/*----------------------------------------------------------------*\
   This loop is used to find out if the truncated element to be added 
matches with the existing element in the mod_w_array. If it matches then 
the existing element repeat_cntr will be incremented and that element 
position is assigned to is_same.
\*-----------------------------------------------------------------*/

	for (j=0; j<i ; j++)
	{
	    ProWstringToString ( mod_w_array_str, mod_w_array[j]);

	    if ( ProUtilStrcmp ( mod_w_array_str, mod_name) == 0)
	    {
		is_same = j;
		repeat_cntr[j]++; 
	    }
	}

/*----------------------------------------------------------------*\
   If the element to be added is repeated, then the matched existing 
element repeat_cntr will be appended to the element.
\*-----------------------------------------------------------------*/

	if (is_same > -1)
	{
	    ProTKSprintf (cntr_line, (char*)"%s(%d)", mod_name, repeat_cntr[is_same]);
	    mod_w_array[i] = ( ProWstring ) malloc ( sizeof (wchar_t) * (strlen (cntr_line)+1));
	    ProStringToWstring ( mod_w_array[i], cntr_line);
	}
	else
	{
	    mod_w_array[i] = (ProWstring ) malloc ( sizeof (wchar_t) * (strlen (mod_name)+1));
	    ProStringToWstring ( mod_w_array[i], mod_name);
	}
        free (mod_name);
    }

    w_ptr = &w_empty;

/*----------------------------------------------------------------*\
 empty wchar_t added as last element to mod_w_array 
\*-----------------------------------------------------------------*/

    mod_w_array[i] = w_ptr;

/*----------------------------------------------------------------*\
   empty wchar_t added as last element to w_array to maintain the size 
equivalent to mod_w_array. Size of w_array (help msgs) and mod_w_array 
(menus ) should be same for the fn ProMenuStringSelect to work properly.
\*-----------------------------------------------------------------*/


    status = ProArrayObjectAdd((ProArray*)&w_array, PRO_VALUE_UNUSED, 1,
            &w_ptr);
    TEST_CALL_REPORT("ProArrayObjectAdd()", "ProTestEditModelitemRel()",
                                        status, status != PRO_TK_NO_ERROR);

    status = ProArraySizeGet (mod_w_array, &num_lines);
    TEST_CALL_REPORT("ProArraySizeGet ()", "ProTestEditModelitemRel()",
					status, status != PRO_TK_NO_ERROR);

    ProStringToWstring(w_name, (char*)"Item Rels");

/*----------------------------------------------------------------*\
   Note: Only for the sub menu strings mod_w_array is passed. For the 
help message w_array is passed. This is to facilitate the user to know 
the original value of truncated string.
\*-----------------------------------------------------------------*/

    status = ProMenuStringsSelect(w_name, (wchar_t **) mod_w_array, 1, (wchar_t **) w_array, &w_select, &num_lines);
    TEST_CALL_REPORT("ProMenuStringsSelect()", "ProTestEditModelitemRel()",
					status, status != PRO_TK_NO_ERROR);

    if ((status != PRO_TK_NO_ERROR) || (num_lines<1))
	return (0); 

    status = ProArraySizeGet((ProArray)w_array, &n_lines);
    TEST_CALL_REPORT("ProArraySizeGet()", "ProTestEditModelitemRel()", 
					status, status != PRO_TK_NO_ERROR);
    for (i=0; i<n_lines-1; i++)
    {
       sel_index = i;
       if (ProUtilWstrCmp(w_select[0], mod_w_array[i])==0)
	   break;
       else
	 sel_index = -1;
    }

    status = ProArrayObjectRemove((ProArray*)&w_array, n_lines-1, 1);
    TEST_CALL_REPORT("ProArrayFree()", "ProTestEditModelitemRel()", 
					status, status != PRO_TK_NO_ERROR);

    status = ProArrayObjectRemove((ProArray*)&mod_w_array, n_lines-1, 1);
    TEST_CALL_REPORT("ProArrayFree()", "ProTestEditModelitemRel()", 
					status, status != PRO_TK_NO_ERROR);

    if (action == USER_RL_EDIT)
    {
/*----------------------------------------------------------------*\
 Since w_select[0] is truncated, w_array[i] is used to show the exact 
 string for modification 
\*-----------------------------------------------------------------*/

        if (sel_index > -1)
	{
	    ProWstringToString(line, w_array[sel_index]);
	    ProTKSprintf(str, (char*)"Enter Relation [%s]:", line);
    	    ProUtilMsgPrint((char*)"gen", (char*)"TEST %0s", str);

    	    status = ProMessageStringRead(PRO_LINE_SIZE, w_line);
	    TEST_CALL_REPORT("ProMessageStringRead", "ProTestEditModelitemRel()",
			status, status != PRO_TK_NO_ERROR);
	    if (status == PRO_TK_NO_ERROR)
	    {
	        w_array[sel_index] = w_line;
	    }
	}
    }
    else
    {
	if (sel_index > -1)
	{
	    status = ProArrayObjectRemove((ProArray*)&w_array, sel_index, 1);
	    TEST_CALL_REPORT("ProArrayFree()", "ProTestEditModelitemRel()", 
					status, status != PRO_TK_NO_ERROR);
	    n_lines--;
	}
    }
	
    status = ProArraySizeGet((ProArray)w_array, &n_lines);
    TEST_CALL_REPORT("ProArraySizeGet()", "ProTestEditModelitemRel()", 
					status, status != PRO_TK_NO_ERROR);

    if (n_lines<1)
    {
	status =  ProRelsetDelete(&relset);
	TEST_CALL_REPORT("ProRelsetDelete()", "ProTestEditModelitemRel()", 
					status, status != PRO_TK_NO_ERROR);
    }
    else
    {
    	status = ProRelsetRelationsSet(&relset, w_array, n_lines);
    	TEST_CALL_REPORT("ProRelsetRelationsSet()", 
	    "ProTestEditModelitemRel()", status, status != PRO_TK_NO_ERROR);
    }
    free (repeat_cntr);

    status = ProArraySizeGet((ProArray)mod_w_array, &n_lines);
    TEST_CALL_REPORT("ProArraySizeGet()", "ProTestEditModelitemRel()", 
					status, status != PRO_TK_NO_ERROR);

/*--------------------------------------------------------------*\
Since malloc is used only for n_lines-1 element in mod_w_array,
free method is called only to those elements.
\*--------------------------------------------------------------*/


    for (i=0; i<n_lines; i++)
    {
	free (mod_w_array[i]);
    }

	
    status = ProArrayFree((ProArray*) &mod_w_array);
    TEST_CALL_REPORT("ProArrayFree()", "ProTestEditModelitemRel()", 
					status, status != PRO_TK_NO_ERROR);

    status = ProArrayFree((ProArray*) &w_array);
    TEST_CALL_REPORT("ProArrayFree()", "ProTestEditModelitemRel()", 
					status, status != PRO_TK_NO_ERROR);

    return (0);
}


/*====================================================================*\
    FUNCTION :	ProTestRegenerateModelitemRel()
    PURPOSE  :  Regenerate relset 
\*====================================================================*/
int ProTestRegenerateModelitemRel(
    ProModelitem *modelitem,
    int action)
{
  ProError status;
  wchar_t w_empty = 0;
  ProRelset relset;

    status = ProModelitemToRelset(modelitem, &relset);
    TEST_CALL_REPORT("ProModelitemToRelset()", 
	"ProTestRegeneratModelitemRel()", 
	    status, status != PRO_TK_NO_ERROR && status != PRO_TK_E_NOT_FOUND);
	
    if (status != PRO_TK_NO_ERROR)
    {
    	ProUtilMsgPrint((char*)"gen", (char*)"TEST %0s", (char*)"No relations found");
	return (0);
    }

    status = ProRelsetRegenerate(&relset);
    TEST_CALL_REPORT("ProRelsetRegenerate()", 
	"ProTestRegeneratModelitemRel()", status, status != PRO_TK_NO_ERROR);

    if (status == PRO_TK_NO_ERROR)
	ProUtilMsgPrint((char*)"gen", (char*)"TEST %0s", (char*)"Relset regenerated successfully");

    return (0);
}

/*====================================================================*\
    FUNCTION :	ProTestRelsetVisitAction()
    PURPOSE  :  Write info about one relset to the file
\*====================================================================*/
int ProTestRelsetVisitAction(
    ProRelset *p_relset,
    FILE *fp)
{
  ProError status;
  ProLine w_line;
  ProModelitem modelitem;
  ProCharLine str_v, line;
  ProParamvalue value;
  int i, n_lines;
  ProWstring *w_array;
  ProUnititem units;

    status = ProRelsetToModelitem(p_relset, &modelitem);
    TEST_CALL_REPORT("ProRelsetToModelitem()", "ProTestrelsetVisitAction()", 
					status, status != PRO_TK_NO_ERROR);
    ProTKFprintf(fp, (char*)"Id %4d  Type %4d\n", modelitem.id, modelitem.type);

    status = ProArrayAlloc(0, sizeof(ProWstring), 1, (ProArray*)&w_array);
    TEST_CALL_REPORT("ProArrayAlloc()", "ProTestRelsetVisitAction()", 
					status, status != PRO_TK_NO_ERROR);
    
    status = ProRelsetRelationsGet(p_relset, &w_array);
    TEST_CALL_REPORT("ProRelsetRelationsGet()", "ProTestRelsetVisitAction()", 
					status, status != PRO_TK_NO_ERROR);
    
    status = ProArraySizeGet((ProArray)w_array, &n_lines);
    TEST_CALL_REPORT("ProArraySizeGet()", "ProTestRelsetVisitAction()", 
					status, status != PRO_TK_NO_ERROR);
    for (i=0; i<n_lines; i++)
    {
	ProWstringToString(line, w_array[i]);
	ProStringToWstring(w_line, line);

	if (strchr(line, '=')!=NULL)
	{
	    w_line[strchr(line, '=') - line] = 0; 

    	    status = ProRelationEvalWithUnits(p_relset, w_line, &value, &units, PRO_B_FALSE);
    	    TEST_CALL_REPORT("ProRelationEvalWithUnits()", "ProTestRelsetVisitAction()", 
					status, status != PRO_TK_NO_ERROR);
	    if (status != PRO_TK_NO_ERROR)
	    	value.type = PRO_PARAM_VOID;
            switch (value.type)
	    {
	    case PRO_PARAM_DOUBLE:
	    	ProTKSprintf(str_v, (char*)"%8.2f", value.value.d_val);
	    	break;
	    case PRO_PARAM_INTEGER:
	    case PRO_PARAM_NOTE_ID:
	    	ProTKSprintf(str_v, (char*)"%d", value.value.i_val);
	        break;
	    case PRO_PARAM_STRING:
	    	ProWstringToString(str_v, value.value.s_val);
	    	break;
	    case PRO_PARAM_BOOLEAN:
	    	ProUtilstrcpy(str_v, value.value.l_val ? "TRUE" : "FALSE");
	    	break;
   	    default:
	    	ProUtilstrcpy(str_v, "ERROR");
	    	break;
	    }
	}
	else
	   str_v[0]='\0'; 
	ProTKFprintf(fp, (char*)"%10s%25s  %10s\n", (char*)" ", line, str_v);
    }

    status = ProArrayFree((ProArray*)&w_array);
    TEST_CALL_REPORT("ProArrayFree()", "ProTestRelsetVisitAction()", 
					status, status != PRO_TK_NO_ERROR);
    return (0);
}

/*====================================================================*\
    FUNCTION :	ProTestModelRelsetInfo()
    PURPOSE  :  Collect info information for all rels in the model
\*====================================================================*/
int ProTestModelRelsetInfo(
    ProMdl *model)
{
  ProError status;
  char fname[PRO_FILE_NAME_SIZE];
  FILE *fp;
  ProPath w_path;
  ProRelset	    *relset;
  int relset_num, i;

    ProTestQcrName(model, (char*)".rls", fname);
    fp = PTApplsUnicodeFopen(fname, "w");

    ProTKFprintf(fp, (char*)"Owner                      Relation           Value\n");           

    status = ProUtilCollectRelset (*model, &relset);
    if (status == PRO_TK_NO_ERROR)
    {
        status = ProArraySizeGet ((ProArray)relset, &relset_num);
        TEST_CALL_REPORT( "ProArraySizeGet()", "ProTestModelRelsetInfo()", 
            status, status != PRO_TK_NO_ERROR );
        for (i = 0; i < relset_num; i++)
        {
            status = (ProError)ProTestRelsetVisitAction (relset+i, fp);
        }
        status = ProArrayFree ((ProArray*)&relset);
        TEST_CALL_REPORT( "ProArrayFree()", "ProTestModelRelsetInfo()", 
            status, status != PRO_TK_NO_ERROR );
    }
    
    fclose(fp);
    ProStringToWstring(w_path, fname);

    ProInfoWindowDisplay(w_path, NULL, NULL);
    return (0);
}