/* Copyright (c) 2024 PTC Inc. and/or Its Subsidiary Companies. All Rights Reserved. */ #include "ProToolkit.h" #include "ProFeature.h" #include "ProAnalysis.h" #include "ProArray.h" #include "ProDtmPnt.h" #include "ProElement.h" #include "ProExtdata.h" #include "ProMessage.h" #include "ProPoint.h" #include "ProSection.h" #include "Pro2dEntdef.h" #include "ProSelection.h" #include "ProSurface.h" #include "ProGraphic.h" #include "ProModelitem.h" #include "ProUtil.h" #include <PTApplsUnicodeUtils.h> #include <UtilString.h> #include "UtilMath.h" static ProFileName msgfil; /*--------------------------------------------------------------------*\ Data structure to describe the information needed by an analysis feature that creates a surface sys. The csys is centered at a datum point on a surface, with its X and Y axes aligned with the U and V mesh lines. The Z axis can be inwards or outwards, by user choice, and the origin can be offset from the datum point by an offset value that is stored as a feature dimension. \*--------------------------------------------------------------------*/ typedef struct surf_csys_data { /* References */ ProSelection point; /* The datum point referenced by the csys */ /* Dimensions */ double offset; /* Application-specific data */ ProBoolean outwards; /* Results storage */ ProCsysdata csysdata; /* The geometry of the csys */ } Surfcsysdata_t; int UsrClassRegister(ProMdl model, ProExtdataClass *class); /*====================================================================*\ FUNCTION : UsrSurfcsysUiAction() PURPOSE : Callback for UI action for surface csys \*====================================================================*/ ProError UsrSurfcsysUiAction( ProAnalysis analysis) { Surfcsysdata_t *data; ProError status; ProSelection *sel; int n_sel; ProModelitem modelitem; ProPoint p; ProDtmpntType ptype; ProError UsrYesnoGet(); /*--------------------------------------------------------------------*\ Ask the user to select a datum point on a surface. Check that it is on a surface, and reject it if it is not. \*--------------------------------------------------------------------*/ ProMessageDisplay(msgfil,"USER Select a point on a surface"); while(1) { if(ProSelect("point",1,NULL,NULL,NULL,NULL,&sel,&n_sel) != PRO_TK_NO_ERROR || n_sel < 0) return(PRO_TK_MSG_USER_QUIT); ProSelectionModelitemGet(sel[0], &modelitem); ProPointInit(modelitem.owner, modelitem.id, &p); if(!UsrPointPtypeGet(modelitem.owner, p, &ptype) || ptype != PRO_DTMPNT_TYPE_ON_SURF) { ProMessageDisplay(msgfil,"USER That is not a point on surf. Select again"); continue; } break; } /*--------------------------------------------------------------------*\ Get the pointer to the application data stored for this analysis feature, and set the datum point in it. \*--------------------------------------------------------------------*/ if(ProAnalysisInfoGet(analysis, (ProAppData*)&data) != PRO_TK_NO_ERROR) return(PRO_TK_GENERAL_ERROR); ProSelectionCopy(sel[0], &data->point); /*--------------------------------------------------------------------*\ Ask the user whether the Z axis is inwards or outwards, and set the answer in the application data. \*--------------------------------------------------------------------*/ ProMessageDisplay(msgfil,"USER Is the Z axis to be outwards? ||| Yes"); if(UsrYesnoGet(msgfil,"YES",&data->outwards) != PRO_TK_NO_ERROR) return(PRO_TK_GENERAL_ERROR); /*--------------------------------------------------------------------*\ Ask the user for the Z offset, and store that, too. \*--------------------------------------------------------------------*/ ProMessageDisplay(msgfil,"USER Enter the Z offset distance|||0.0"); status = ProMessageDoubleRead(NULL, &data->offset); if(status == PRO_TK_MSG_USER_QUIT) return(PRO_TK_GENERAL_ERROR); if(status != PRO_TK_NO_ERROR) data->offset = 0.0; return(PRO_TK_NO_ERROR); } /*====================================================================*\ FUNCTION : UsrSurfcsysDimsAction() PURPOSE : Callback for Dims action for surface csys \*====================================================================*/ ProError UsrSurfcsysDimsAction( ProAnalysis analysis, double **dims) { Surfcsysdata_t *data; /*--------------------------------------------------------------------*\ Get the application data for this analysis \*--------------------------------------------------------------------*/ if(ProAnalysisInfoGet(analysis, (ProAppData*)&data) != PRO_TK_NO_ERROR) return(PRO_TK_GENERAL_ERROR); /*--------------------------------------------------------------------*\ Add the csys offset value as a feature dimension \*--------------------------------------------------------------------*/ ProArrayObjectAdd((ProArray*)dims, -1, 1, &data->offset); return(PRO_TK_NO_ERROR); } /*====================================================================*\ FUNCTION : UsrSurfcsysInfoallocAction() PURPOSE : Callback to allocate application data needed to describe the surface csys \*====================================================================*/ ProError UsrSurfcsysInfoallocAction( ProAnalysis analysis) { Surfcsysdata_t *data; /*--------------------------------------------------------------------*\ Allocate a data structure \*--------------------------------------------------------------------*/ data = (Surfcsysdata_t*)calloc(1, sizeof(Surfcsysdata_t)); /*--------------------------------------------------------------------*\ Put the data pointer into the analysis \*--------------------------------------------------------------------*/ ProAnalysisInfoSet(analysis, data); return(PRO_TK_NO_ERROR); } /*====================================================================*\ FUNCTION : UsrSurfcsysInfofreeAction() PURPOSE : Callback to free the application data for surface csys \*====================================================================*/ ProError UsrSurfcsysInfofreeAction( ProAnalysis analysis) { Surfcsysdata_t *data; /*--------------------------------------------------------------------*\ Get the data pointer from the analysis \*--------------------------------------------------------------------*/ if(ProAnalysisInfoGet(analysis, (ProAppData*)&data) != PRO_TK_NO_ERROR) return(PRO_TK_GENERAL_ERROR); /*--------------------------------------------------------------------*\ Free the data \*--------------------------------------------------------------------*/ free(data); /*--------------------------------------------------------------------*\ Set the data pointer in the analysis to NULL \*--------------------------------------------------------------------*/ ProAnalysisInfoSet(analysis, NULL); return(PRO_TK_NO_ERROR); } /*====================================================================*\ FUNCTION : UsrSurfcsysCompcheckAction() PURPOSE : Callback to tell Pro/E whether computation can be performed for surface csys analysis feature \*====================================================================*/ ProError UsrSurfcsysCompcheckAction( ProAnalysis analysis) { Surfcsysdata_t *data; /*--------------------------------------------------------------------*\ Get the analysis data \*--------------------------------------------------------------------*/ if(ProAnalysisInfoGet(analysis, (ProAppData*)&data) != PRO_TK_NO_ERROR) return(PRO_TK_GENERAL_ERROR); /*--------------------------------------------------------------------*\ Return NO_ERROR if the datum point selection is set OK \*--------------------------------------------------------------------*/ return(data->point!=NULL?PRO_TK_NO_ERROR:PRO_TK_GENERAL_ERROR); } /*====================================================================*\ FUNCTION : UsrSurfcsysComputeAction() PURPOSE : Callback to perform the surface csys computation \*====================================================================*/ ProError UsrSurfcsysComputeAction( ProAnalysis analysis) { Surfcsysdata_t *data; ProModelitem modelitem; ProPoint p; ProVector pos; ProSurface surface; ProUvParam uv; ProVector normal, der1[2]; ProFeature feature; /*--------------------------------------------------------------------*\ Get the application data from the analysis \*--------------------------------------------------------------------*/ if(ProAnalysisInfoGet(analysis, (ProAppData*)&data) != PRO_TK_NO_ERROR) return(PRO_TK_GENERAL_ERROR); /*--------------------------------------------------------------------*\ Get the location of the datum point \*--------------------------------------------------------------------*/ ProSelectionModelitemGet(data->point, &modelitem); ProPointInit(modelitem.owner, modelitem.id, &p); ProPointCoordGet(p, data->csysdata.origin); /*--------------------------------------------------------------------*\ Find the surface the datum point sits on, and find its first derivative vectors and the normal \*--------------------------------------------------------------------*/ UsrPointSrfGet(data->point, &surface); ProSurfaceParamEval(modelitem.owner, surface, data->csysdata.origin, uv); ProSurfaceXyzdataEval(surface, uv, NULL, der1, NULL, normal); /*--------------------------------------------------------------------*\ Flip and offset if necessary \*--------------------------------------------------------------------*/ if(!data->outwards) ProUtilVectorScale(-1.0, normal, normal); ProUtilVectorsLincom(1.0, data->csysdata.origin, data->offset, normal, data->csysdata.origin); /*--------------------------------------------------------------------*\ Copy this information to the application data as a csys geometry \*--------------------------------------------------------------------*/ memcpy(data->csysdata.x_vector, der1[0], sizeof(ProVector)); ProUtilVectorNormalize(data->csysdata.x_vector, data->csysdata.x_vector); memcpy(data->csysdata.z_vector, normal, sizeof(ProVector)); ProUtilVectorNormalize(data->csysdata.z_vector, data->csysdata.z_vector); ProUtilVectorCross(data->csysdata.z_vector, data->csysdata.x_vector, data->csysdata.y_vector); return(PRO_TK_NO_ERROR); } /*====================================================================*\ FUNCTION : UsrSurfcsysDisplayAction() PURPOSE : Callback to display the results of the analysis computation \*====================================================================*/ ProError UsrSurfcsysDisplayAction( ProAnalysis analysis) { Surfcsysdata_t *data; ProVector pos; /*--------------------------------------------------------------------*\ Get the application data from the analysis \*--------------------------------------------------------------------*/ if(ProAnalysisInfoGet(analysis, (ProAppData*)&data) != PRO_TK_NO_ERROR) return(PRO_TK_GENERAL_ERROR); /*--------------------------------------------------------------------*\ Draw a line for the X vector \*--------------------------------------------------------------------*/ ProGraphicsPenPosition(data->csysdata.origin); pos[0]=data->csysdata.origin[0]+data->csysdata.x_vector[0]; pos[1]=data->csysdata.origin[1]+data->csysdata.x_vector[1]; pos[2]=data->csysdata.origin[2]+data->csysdata.x_vector[2]; ProGraphicsLineDraw(pos); /*--------------------------------------------------------------------*\ Draw a line for the Y vector \*--------------------------------------------------------------------*/ ProGraphicsPenPosition(data->csysdata.origin); pos[0]=data->csysdata.origin[0]+data->csysdata.y_vector[0]; pos[1]=data->csysdata.origin[1]+data->csysdata.y_vector[1]; pos[2]=data->csysdata.origin[2]+data->csysdata.y_vector[2]; ProGraphicsLineDraw(pos); /*--------------------------------------------------------------------*\ Draw a line for the Z vector \*--------------------------------------------------------------------*/ ProGraphicsPenPosition(data->csysdata.origin); pos[0]=data->csysdata.origin[0]+data->csysdata.z_vector[0]; pos[1]=data->csysdata.origin[1]+data->csysdata.z_vector[1]; pos[2]=data->csysdata.origin[2]+data->csysdata.z_vector[2]; ProGraphicsLineDraw(pos); return(PRO_TK_NO_ERROR); } /*====================================================================*\ FUNCTION : UsrSurfcsysOutputAction() PURPOSE : Callback to write textual information about the result of the computation \*====================================================================*/ ProError UsrSurfcsysOutputAction( ProAnalysis analysis, ProLine **lines) { Surfcsysdata_t *data; ProCharLine buff; ProLine ll[4]; /*--------------------------------------------------------------------*\ Get the application dara from the analysis \*--------------------------------------------------------------------*/ if(ProAnalysisInfoGet(analysis, (ProAppData*)&data) != PRO_TK_NO_ERROR) return(PRO_TK_GENERAL_ERROR); /*--------------------------------------------------------------------*\ Write the origin of the csys \*--------------------------------------------------------------------*/ ProTKSprintf(buff,"Csys is at location (%0.2f, %0.2f, %0.2f)", data->csysdata.origin[0], data->csysdata.origin[1], data->csysdata.origin[2]); ProStringToWstring(ll[0], buff); /*--------------------------------------------------------------------*\ X vector \*--------------------------------------------------------------------*/ ProTKSprintf(buff," X vector (%0.2f, %0.2f, %0.2f)", data->csysdata.x_vector[0], data->csysdata.x_vector[1], data->csysdata.x_vector[2]); ProStringToWstring(ll[1], buff); /*--------------------------------------------------------------------*\ Y vector \*--------------------------------------------------------------------*/ ProTKSprintf(buff," Y vector (%0.2f, %0.2f, %0.2f)", data->csysdata.y_vector[0], data->csysdata.y_vector[1], data->csysdata.y_vector[2]); ProStringToWstring(ll[2], buff); /*--------------------------------------------------------------------*\ Z vector \*--------------------------------------------------------------------*/ ProTKSprintf(buff," Z vector (%0.2f, %0.2f, %0.2f)", data->csysdata.z_vector[0], data->csysdata.z_vector[1], data->csysdata.z_vector[2]); ProStringToWstring(ll[3], buff); /*--------------------------------------------------------------------*\ Add the four lines to the output array \*--------------------------------------------------------------------*/ ProArrayObjectAdd((ProArray*)lines, -1, 4, ll); return(PRO_TK_NO_ERROR); } /*====================================================================*\ FUNCTION : UsrSurfcsysSavecheckAction() PURPOSE : Callback to tell Pro/E whether the analysis application data can be saved \*====================================================================*/ ProError UsrSurfcsysSavecheckAction( ProAnalysis analysis) { return(PRO_TK_NO_ERROR); } /*====================================================================*\ FUNCTION : UsrSurfcsysInfosaveAction() PURPOSE : Callback to tell Pro/E what element references are required by the analysis feature, and save the rest of the info to Ext Data \*====================================================================*/ ProError UsrSurfcsysInfosaveAction( ProAnalysis analysis, ProFeature *feature, ProSelection **references) { Surfcsysdata_t *data; ProSelection reference; /*--------------------------------------------------------------------*\ Get the application data from the analysis \*--------------------------------------------------------------------*/ if(ProAnalysisInfoGet(analysis, (ProAppData*)&data) != PRO_TK_NO_ERROR) return(PRO_TK_GENERAL_ERROR); /*--------------------------------------------------------------------*\ Output the reference to the datum point \*--------------------------------------------------------------------*/ ProSelectionCopy(data->point, &reference); ProArrayObjectAdd((ProArray*)references, -1, 1, &reference); /*--------------------------------------------------------------------*\ Save the "outwards" option \*--------------------------------------------------------------------*/ if(!UsrOutwardsSave(feature, data->outwards)) return(PRO_TK_GENERAL_ERROR); return(PRO_TK_NO_ERROR); } ProError UsrSurfcsysDimFilter( ProDimension *dimension, ProAppData data) { static ProBoolean first_time = PRO_B_TRUE; if (first_time) { first_time = PRO_B_FALSE; return PRO_TK_NO_ERROR; } else return PRO_TK_CONTINUE; } ProError UsrSurfcsysDimAction ( ProDimension *dimension, ProError status, ProAppData data) { data = (ProAppData)dimension; return PRO_TK_NO_ERROR; } /*====================================================================*\ FUNCTION : UsrSurfcsysInforetrieveAction() PURPOSE : Callback to get the references Pro/E has stored with the analysis feature, and retrieve the rest from Ext Data \*====================================================================*/ ProError UsrSurfcsysInforetrieveAction( ProAnalysis analysis, ProFeature *feature, ProSelection *references) { Surfcsysdata_t *data; ProError status; ProDimension first_dim; double dim_value; /*--------------------------------------------------------------------*\ Get the application data from the analysis \*--------------------------------------------------------------------*/ if(ProAnalysisInfoGet(analysis, (ProAppData*)&data) != PRO_TK_NO_ERROR) return(PRO_TK_GENERAL_ERROR); /*--------------------------------------------------------------------*\ Copy the first reference to the application as the datum point \*--------------------------------------------------------------------*/ ProSelectionCopy(references[0], &data->point); /*--------------------------------------------------------------------*\ Retrieve the "outwards" option from Ext Data \*--------------------------------------------------------------------*/ UsrOutwardsRetrieve(feature, &data->outwards); /*--------------------------------------------------------------------*\ If the feature has a dimension, take its value as the offset \*--------------------------------------------------------------------*/ status = ProFeatureDimensionVisit(feature, (ProDimensionVisitAction)UsrSurfcsysDimAction, (ProDimensionFilterAction)UsrSurfcsysDimFilter, (ProAppData)&first_dim); status = ProDimensionValueGet(&first_dim, &dim_value); data->offset = dim_value; return(PRO_TK_NO_ERROR); } /*====================================================================*\ FUNCTION : UsrSurfcsysInfocopyAction() PURPOSE : Callback to copy application information from one analysis to another. \*====================================================================*/ ProError UsrSurfcsysInfocopyAction( ProAnalysis from, ProAnalysis to) { Surfcsysdata_t *fdata, *tdata; /*--------------------------------------------------------------------*\ Get the application data from the analyses \*--------------------------------------------------------------------*/ if(ProAnalysisInfoGet(from, (ProAppData*)&fdata) != PRO_TK_NO_ERROR) return(PRO_TK_GENERAL_ERROR); if(ProAnalysisInfoGet(to, (ProAppData*)&tdata) != PRO_TK_NO_ERROR) return(PRO_TK_GENERAL_ERROR); /*--------------------------------------------------------------------*\ Copy the application-specific data (everything except references) \*--------------------------------------------------------------------*/ tdata->outwards = fdata->outwards; tdata->offset = fdata->offset; return(PRO_TK_NO_ERROR); } /*====================================================================*\ FUNCTION : UsrSurfcsysResultAction() PURPOSE : Callback to give Pro/E the feature parameters and geometry that the analysis feature must contain \*====================================================================*/ ProError UsrSurfcsysResultAction( ProAnalysis analysis, ProBoolean names_only, ProAnalysisParameter **parameters, ProAnalysisGeomitem **geometry) { Surfcsysdata_t *data; ProAnalysisGeomitem geomitem; ProAnalysisParameter param; /*--------------------------------------------------------------------*\ Get the application data from the analysis \*--------------------------------------------------------------------*/ if(ProAnalysisInfoGet(analysis, (ProAppData*)&data) != PRO_TK_NO_ERROR) return(PRO_TK_GENERAL_ERROR); /*--------------------------------------------------------------------*\ Specify a CSYS DATUM with the geometry stored in the application data \*--------------------------------------------------------------------*/ ProStringToWstring(geomitem.name,"SURF_CSYS"); geomitem.create = PRO_B_TRUE; geomitem.type = PRO_ANALYSIS_CSYS; if(!names_only) { ProArrayAlloc(1, sizeof(ProAnalysisEntity), 1, (ProArray*)&geomitem.shapes); memcpy(geomitem.shapes[0].csys.origin, data->csysdata.origin, sizeof(ProVector)); memcpy(geomitem.shapes[0].csys.x_vector, data->csysdata.x_vector, sizeof(ProVector)); memcpy(geomitem.shapes[0].csys.y_vector, data->csysdata.y_vector, sizeof(ProVector)); memcpy(geomitem.shapes[0].csys.z_vector, data->csysdata.z_vector, sizeof(ProVector)); } /*--------------------------------------------------------------------*\ Output the csys geometry description \*--------------------------------------------------------------------*/ ProArrayAlloc(0, sizeof(ProAnalysisGeomitem), 1, (ProArray*)geometry); ProArrayObjectAdd((ProArray*)geometry, -1, 1, &geomitem); return(PRO_TK_NO_ERROR); } int UsrExtAnalysisRegister () { ProAnalysisFuncsData data; ProStringToWstring(msgfil,"umsg.txt"); /*--------------------------------------------------------------------*\ Build the description of the surface csys analysis feature data, and register it with Pro/E \*--------------------------------------------------------------------*/ memset(&data, '\0', sizeof(ProAnalysisFuncsData)); ProStringToWstring(data.type, "Surface Csys"); data.ui_action = UsrSurfcsysUiAction; data.dims_action = UsrSurfcsysDimsAction; data.infoalloc_action = UsrSurfcsysInfoallocAction; data.infofree_action = UsrSurfcsysInfofreeAction; data.compcheck_action = UsrSurfcsysCompcheckAction; data.compute_action = UsrSurfcsysComputeAction; data.display_action = UsrSurfcsysDisplayAction; data.output_action = UsrSurfcsysOutputAction; data.savecheck_action = UsrSurfcsysSavecheckAction; data.infosave_action = UsrSurfcsysInfosaveAction; data.inforetrieve_action = UsrSurfcsysInforetrieveAction; data.infocopy_action = UsrSurfcsysInfocopyAction; data.result_action = UsrSurfcsysResultAction; ProAnalysisTypeRegister(&data); return(0); } /*====================================================================*\ FUNCTION : UsrPointPtypeGet() PURPOSE : Utility to get the placement type of a datum point \*====================================================================*/ int UsrPointPtypeGet( ProSolid owner, ProPoint p, ProDtmpntType *ptype) { ProElempathItem items[5]; ProElempath epath; ProValue value; ProValueData vdata; int id; ProGeomitem geomitem; ProFeature feature; /*--------------------------------------------------------------------*\ Get the feature that owns the point \*--------------------------------------------------------------------*/ ProPointIdGet(p, &id); ProModelitemInit(owner, id, PRO_POINT, &geomitem); ProGeomitemFeatureGet(&geomitem, &feature); /*--------------------------------------------------------------------*\ Get the placement type from the element tree \*--------------------------------------------------------------------*/ items[0].type = PRO_ELEM_PATH_ITEM_TYPE_ID; items[0].path_item.elem_id = PRO_E_DPOINT_POINTS_ARRAY; items[1].type = PRO_ELEM_PATH_ITEM_TYPE_INDEX; items[1].path_item.elem_index = 0; items[2].type = PRO_ELEM_PATH_ITEM_TYPE_ID; items[2].path_item.elem_id = PRO_E_DPOINT_PLA_CONSTRAINTS; items[3].type = PRO_ELEM_PATH_ITEM_TYPE_INDEX; items[3].path_item.elem_index = 0; items[4].type = PRO_ELEM_PATH_ITEM_TYPE_ID; items[4].path_item.elem_id = PRO_E_DPOINT_PLA_CONSTR_TYPE; ProElempathAlloc(&epath); ProElempathDataSet(epath, items, 5); if(ProFeatureElemValueGet(&feature, epath, &value) != PRO_TK_NO_ERROR) return(0); if(ProValueDataGet(value, &vdata) != PRO_TK_NO_ERROR) return(0); *ptype = (ProDtmpntType)vdata.v.i; return(1); } /*====================================================================*\ FUNCTION : UsrPointSrfGet() PURPOSE : Utility to get the surface a datum point is placed on. \*====================================================================*/ int UsrPointSrfGet( ProSelection point, ProSurface *surface) { ProElempathItem items[5]; ProElempath epath; ProValue value; ProValueData vdata; int id; ProGeomitem geomitem; ProFeature feature; ProSelection sel; /*--------------------------------------------------------------------*\ Get the feature that owns the datum point \*--------------------------------------------------------------------*/ ProSelectionModelitemGet(point, &geomitem); ProGeomitemFeatureGet(&geomitem, &feature); /*--------------------------------------------------------------------*\ Get the surface from the element tree \*--------------------------------------------------------------------*/ items[0].type = PRO_ELEM_PATH_ITEM_TYPE_ID; items[0].path_item.elem_id = PRO_E_DPOINT_POINTS_ARRAY; items[1].type = PRO_ELEM_PATH_ITEM_TYPE_INDEX; items[1].path_item.elem_index = 0; items[2].type = PRO_ELEM_PATH_ITEM_TYPE_ID; items[2].path_item.elem_id = PRO_E_DPOINT_PLA_CONSTRAINTS; items[3].type = PRO_ELEM_PATH_ITEM_TYPE_INDEX; items[3].path_item.elem_index = 0; items[4].type = PRO_ELEM_PATH_ITEM_TYPE_ID; items[4].path_item.elem_id = PRO_E_DPOINT_PLA_CONSTR_REF; ProElempathAlloc(&epath); ProElempathDataSet(epath, items, 5); if(ProFeatureElemValueGet(&feature, epath, &value) != PRO_TK_NO_ERROR) return(0); if(ProValueDataGet(value, &vdata) != PRO_TK_NO_ERROR) return(0); sel = (ProSelection)vdata.v.r; ProSelectionModelitemGet(sel, &geomitem); ProSurfaceInit(geomitem.owner, geomitem.id, surface); return(1); } /*====================================================================*\ FUNCTION : UsrYesnoGet() PURPOSE : Prompt for a yes/no answer \*====================================================================*/ ProError UsrYesnoGet( wchar_t *msgfil, char *def, /* INPUT : default answer */ ProBoolean *yes)/* Output: TRUE = yes, FALSE no */ { wchar_t wreply[4]; char reply[4]; ProError status; while(1) { /*--------------------------------------------------------------------*\ Read string from keyboard \*--------------------------------------------------------------------*/ status = ProMessageStringRead(4, wreply); if(status == PRO_TK_MSG_USER_QUIT) return(PRO_TK_MSG_USER_QUIT); /*--------------------------------------------------------------------*\ Convert reply (or default) to uppercase C string \*--------------------------------------------------------------------*/ if(status == PRO_TK_NO_ERROR) ProWstringToString(reply,wreply); else strcpy(reply, def); ProUtilStringUpper(reply,reply); /*--------------------------------------------------------------------*\ Output response \*--------------------------------------------------------------------*/ if(reply[0] == 'Y') { *yes = PRO_B_TRUE; return(PRO_TK_NO_ERROR); } if(reply[0] == 'N') { *yes = PRO_B_FALSE; return(PRO_TK_NO_ERROR); } /*--------------------------------------------------------------------*\ If reply was neither yes or no, ask again. \*--------------------------------------------------------------------*/ ProMessageDisplay(msgfil,"USER Please answer Y or N : "); } } #define CLASS_NAME "SURFCSYS" /*====================================================================*\ FUNCTION : UsrOutwardsSave() PURPOSE : Save the "outwards" flag to external data \*====================================================================*/ int UsrOutwardsSave( ProFeature *feature, ProBoolean outwards) { ProExtdataClass class; ProCharName slotname; if(!UsrClassRegister(feature->owner, &class)) return(0); ProTKSprintf(slotname,"OUTWARDS_%d",feature->id); UsrIntegerSave(&class, slotname, (int)outwards); return(1); } /*====================================================================*\ FUNCTION : UsrOutwardsRetrieve() PURPOSE : Retrieve the outwards flag from external data \*====================================================================*/ int UsrOutwardsRetrieve( ProFeature *feature, ProBoolean *outwards) { ProExtdataClass class; ProCharName slotname; int i; if(!UsrClassExists(feature->owner, CLASS_NAME, &class)) return(0); ProTKSprintf(slotname,"OUTWARDS_%d",feature->id); if(!UsrIntegerRetrieve(&class, slotname, &i)) return(0); *outwards = i==0 ? PRO_B_FALSE : PRO_B_TRUE; return(1); } /*====================================================================*\ FUNCTION : UsrClassRegister() PURPOSE : Register a data class, if it does not already exist \*====================================================================*/ int UsrClassRegister( ProMdl model, ProExtdataClass *class) { ProName cname; if(!UsrClassExists(model, CLASS_NAME, class)) { ProStringToWstring(cname, CLASS_NAME); if(ProExtdataClassRegister(model, cname, class) != PROEXTDATA_TK_NO_ERROR) return(0); } return(1); } /*====================================================================*\ FUNCTION : UsrIntegerSave() PURPOSE : Utility to save an integer slot \*====================================================================*/ int UsrIntegerSave( ProExtdataClass *class, char *slotname, int i) { ProExtdataSlot slot; ProName sname; /*--------------------------------------------------------------------*\ If the specified slot does not exist, create it \*--------------------------------------------------------------------*/ ProStringToWstring(sname, slotname); if(ProExtdataSlotCreate(class, sname, &slot) != PROEXTDATA_TK_NO_ERROR) { slot.p_class = class; ProStringToWstring(slot.slot_name, slotname); } /*--------------------------------------------------------------------*\ Write the integer to the data slot \*--------------------------------------------------------------------*/ ProExtdataSlotWrite(&slot, KEY_BY_NAME, PRO_INTEGER_TYPE, 0, &i); return(1); } /*====================================================================*\ FUNCTION : UsrIntegerRetrieve() PURPOSE : Retrieve an integer \*====================================================================*/ int UsrIntegerRetrieve( ProExtdataClass *class, char *slotname, int *i) { ProExtdataSlot slot; int *data; int size, type; /*--------------------------------------------------------------------*\ Read the integer from the data slot \*--------------------------------------------------------------------*/ slot.p_class = class; ProStringToWstring(slot.slot_name, slotname); if(ProExtdataSlotRead(&slot, KEY_BY_NAME, &type, &size, (void**)&data) != PROEXTDATA_TK_NO_ERROR) return(0); *i = *data; return(1); } /*====================================================================*\ FUNCTION : UsrClassExists PURPOSE : Check if the specified class exists \*====================================================================*/ int UsrClassExists( ProMdl model, char *name, ProExtdataClass *class) { ProExtdataErr status; int n_classes, c; ProName *classes; status = ProExtdataClassNamesList(model, &n_classes, &classes); if(status != PROEXTDATA_TK_NO_ERROR) return(0); for(c=0;c<n_classes;c++) { if(!ProUtilStrwscmp(name, classes[c])) { class->p_model = model; ProStringToWstring(class->class_name, name); ProArrayFree((ProArray *)&classes); return(1); } } ProArrayFree((ProArray *)&classes); return(0); }