Rev 162 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
/************************************************************************** Copyright (C) 1995 Embedded Solutions* All rights reserved** file: src\config.c** purpose: Configuration module* This module will read in the configuration file and set up* all the configuration parameters** functions* compact - Compact a string* conf_menu - Configuration Menu* configure - Read in the configuration file* d_class - Update the class information* d_cntry - Display / Update Country list* d_config - Configuration Update and Display* define_class - Update the class information* define_config - Alter the configuration file* define_country - Define a new entry in the county list* display_class - Display the class information* display_config - Display the marathon configuration* display_country - Display the current country list* f_comp_int - Qsort callback: Sort by team* r_config - Read in the configuration file* rd_config - Read in the configuration file* valid_field - Validate a team number* wt_config - Write out the configuration file** programmer: David Purdie** revision date by reason* 00.0 27/01/95 DDP Tidies up the program and formatted the file***************************************************************************/#include "consts.h"#include "structs.h"#include "proto.h"#include "QApplication"/*** Local definitions*/char confile[20]; /* Name of the config file */char datfile[20]; /* Name of the data file */char filebase[20]; /* Event file name base */MARA_CFG config; /* Working configuration *///MARA_CFG newcfg; /* Play configuration *///t_class_summary class_summary; /* Class summary data *///menu_table cnf_menu[] = {// {'1', "Display current configuration", display_config},// {'2', "Alter configuration", ( void ( * )( void ) ) define_config},// {'3', "Display category configuration", display_class},// {'4', "Alter category configuration", ( void ( * )( void ) ) define_class},// {'5', "Display country list", display_country},// {'6', "Alter country list", define_country},// {'7', "Display winners list", display_winners},// {'8', "Alter winners list", ( void ( * )( void ) ) define_winners},// {'q', "Return to main menu", 0},// {'\0'}//};/*========================================================================** Read in the configuration file** Purpose:* This function is called to read in the configuration file** Parameters:* c_name Name of the configuartion file* mode TRUE: Create the file** Returns:* Returns TRUE if the system was configured ok**========================================================================*/bool configure( char *c_name, int mode ){FILE * fcon;bool ok = FALSE;strncpy( filebase, c_name, 8 );strcpy( confile, filebase );strcat( confile, ".cnf" );strcpy( datfile, filebase );strcat( datfile, ".dat" );fcon = fopen( confile, "rb" );if ( fcon )fclose( fcon );if( mode ){// if( fcon )// {// printf( "Configuration file already exists" );// ok = FALSE;// }// else// {// ok = define_config( ); /* Generate the configuration */// if( ok )// ok = define_class( );// }}else if( fcon )ok = rd_config( ); /* read in the existing config */else{ok = FALSE;printf( "Configuration file not found" );}/*** Post read calculations and fixups*/if( config.datafilename[0] ){strcpy( datfile, config.datafilename );strcat( datfile, ".dat" );}config.nonequestrian_class = lookup_class( config.nonequestrian_class_abr, &config );return ( ok );}///*========================================================================// *// * Configuration Menu// *// * Purpose:// * This function is called to display the configuartion menu// *// * Parameters:// * None// *// * Returns:// * Nothing// *// *========================================================================*///void conf_menu( void )//{// do_menu( "Event configuration", "Select option", cnf_menu );//}/*========================================================================** Alter the configuration file** Purpose:* This function is called to alter the configuration file** Parameters:* None** Returns:* TRUE - Configuration changed* FALSE - Configuration not changed**========================================================================*///bool define_config( void )//{// int i, j;// int error;// bool changed = FALSE;// int num_teams;// /*// ** Copy working configuration into a temp structure for// ** use within the function// */// newcfg = config;// do// {// error = 0;// num_teams = 0;// d_config( &newcfg, M_UPDATE );// printf( "" );// compact( newcfg.event_name ); /* Rip of leading white_space */// for( i = 0; i < MAX_LEGS; i++ )// compact( newcfg.leg_name[i] );// compact( newcfg.addendum );// compact( newcfg.datafilename );// /*// * Do all sorts of consistency tests on the data// * Firstly - calculate the number of legs. Justify the data in the array// */// newcfg.num_legs = 0;// for( i = 0; i < MAX_LEGS; i++ )// if( newcfg.leg_name[i][0] )// newcfg.num_legs++;// for( i = newcfg.num_legs; i < MAX_LEGS; i++ )// if( newcfg.leg_name[i][0] )// {// printf( "Configuration error: Missing leg" );// error++;// }// /*// * Now do the team numbering stuff// */// for( i = 0; i < MAX_TMS_SPLIT; i++ )// {// if( newcfg.t_def[i].start == 0 && newcfg.t_def[i].end == 0 )// continue;// if( newcfg.t_def[i].start > newcfg.t_def[i].end )// {// printf// ( "Team definition error : End greater than start. %d to %d",// newcfg.t_def[i].start, newcfg.t_def[i].end );// error++;// }// for( j = 0; j < i; j++ )// {// if( ( newcfg.t_def[i].start >= newcfg.t_def[j].start// && newcfg.t_def[i].start <= newcfg.t_def[j].end )// || ( newcfg.t_def[i].end >= newcfg.t_def[j].start// && newcfg.t_def[i].end <= newcfg.t_def[j].end ) )// {// printf// ( "Team definition error : Overlapping definition. %d to %d",// newcfg.t_def[i].start, newcfg.t_def[i].end );// error++;// }// }// }// /*// * Determine the number of team splits// * There may be blank entries - these will be removed by sorting the array// */// qsort( ( char * ) newcfg.t_def, MAX_TMS_SPLIT, sizeof( *newcfg.t_def ), f_comp_int );// for( newcfg.num_teams = 0; newcfg.num_teams < MAX_TMS_SPLIT; newcfg.num_teams++ )// if( !newcfg.t_def[newcfg.num_teams].start )// break;// newcfg.min_team = newcfg.t_def[0].start;// newcfg.max_team = newcfg.t_def[newcfg.num_teams - 1].end;// /*// ** Limit the number of entrants// */// for( i = 0; i < MAX_TMS_SPLIT; i++ )// {// if( newcfg.t_def[i].start )// {// num_teams += newcfg.t_def[i].end - newcfg.t_def[i].start + 1;// }// }//#if defined(LIMIT_TEAMS) && (LIMIT_TEAMS > 0)// if( num_teams > LIMIT_TEAMS )// {// printf( "Maximum number of teams exceeded - reduce number of teams" );// error++;// }//#endif//#if defined (HI_TECH_C) || defined (__TURBOC__)// /*// * Ensure that the number of teams allocated can fit within available// * Memory space. Ie: Can we malloc the report data structures// */// {// long sz;// sz = sizeof( ty_s_data ) > sizeof( ty_s_aux ) ?// sizeof( ty_s_data ) : sizeof( ty_s_aux );// if( sz * ( newcfg.max_team - newcfg.min_team + 2 ) > ( 1024L * 64L ) )// {// printf( "Too many teams: Reduce team spread." );// error++;// }// }//#endif// /*// ** Ensure the non-equestrian class and the equestrian leg are valid// */// if( newcfg.equestrian_leg )// {// if( newcfg.equestrian_leg > newcfg.num_legs )// {// printf( "Invalid non-equestrian leg number." );// error++;// }// /*// ** Ensure that the entered non-equestrian class name does exist// */// newcfg.nonequestrian_class = lookup_class( newcfg.nonequestrian_class_abr, &newcfg );// if( newcfg.nonequestrian_class == 0 )// printf( "WARNING: Non-equestrian class not found" );// }// abort_flag = FALSE;// if( error )// {// printf( "Configuration error - error must be corrected" );// printf( "Any key to continue " );// ( void ) getinp( );// continue;// }// else// {// printf( "Install configuration (Y)es, (D)iscard, (E)dit again :" );// switch ( getfnc( "*YDEA" ) )// {// case 'Y':// error = ( newcfg.num_legs == 0 || newcfg.num_teams == 0 );// if( error )// printf( "Configuration not installed. No legs or teams defined" );// else// {// config = newcfg;// wt_config( ); /* Write out the data */// changed = TRUE;// }// break;// case 'D':// break;// default:// error = TRUE;// break;// }// }// }// while( error );// return ( changed );//}/*========================================================================** Display the marathon configuration** Purpose:* This function is called to Display the marathon configuration** Parameters:* None** Returns:* Nothing**========================================================================*///void display_config( void )//{// d_config( &config, M_DISPLAY );// cur( 0, n_lines - 1 );// printf( "Any key to return to main menu :" );// getinp( );//}/*========================================================================** Display the class information** Purpose:* This function is called to display the class information** Parameters:* None** Returns:* Nothing**========================================================================*///void display_class( void )//{// d_class( &config, M_DISPLAY );// cur( 0, n_lines - 1 );// printf( "Any key to continue :" );// getinp( );//}/*========================================================================** Update the class information** Purpose:* This function is called to update the class information** Parameters:* None** Returns:* Nothing**========================================================================*///bool define_class( void )//{// int error;// int i;// bool changed = FALSE;// /*// ** Copy working configuration into a temp structure for// ** use within the function// */// newcfg = config;// do// {// error = 0;// d_class( &newcfg, M_UPDATE );// printf( "" );// /*// ** Now do the Class definitions// */// for( i = 0; i < MAX_CLASS; i++ )// {// compact( newcfg.team_class[i].abr );// compact( newcfg.team_class[i].full_name );// }// for( i = 0; i < MAX_CLASS; i++ )// {// if( ( newcfg.team_class[i].abr[0] == '\0' ) != ( newcfg.team_class[i].full_name[0] == '\0' ) )// {// printf( "Configuration error. Class without description" );// error++;// }// if( newcfg.team_class[i].abr[0] != '\0' && newcfg.team_class[i].start < 0L )// {// printf( "Configuration error. Bad start time on class" );// error++;// }// }// newcfg.num_class = 0;// for( i = 0; i < MAX_CLASS; i++ )// if( newcfg.team_class[i].full_name[0] )// newcfg.num_class++;// for( i = newcfg.num_class; i < MAX_CLASS; i++ )// if( newcfg.team_class[i].full_name[0] )// {// printf( "Configuration error: Missing Class name. Gaps not allowed" );// error++;// }// if( newcfg.num_class == 0 )// {// printf( "Error: No categories defined" );// error++;// }// newcfg.nonequestrian_class = lookup_class( newcfg.nonequestrian_class_abr, &newcfg );// if( newcfg.equestrian_leg && newcfg.nonequestrian_class == 0 )// printf( "WARNING: Non-equestrian class not found" );// abort_flag = FALSE;// if( error )// {// printf( "Any key to continue " );// getinp( );// }// else// {// printf( "Install configuration (Y)es, (D)iscard, (E)dit again :" );// switch ( getfnc( "*YDEA" ) )// {// case 'Y':// config = newcfg;// wt_config( );// changed = TRUE;// break;// case 'D':// break;// default:// error = TRUE;// break;// }// }// } while( error && ! abort_flag );// return ( changed );//}/*========================================================================** Update the class information** Purpose:* This function is called to update the class information* Display the marathon classes from the system parameters.** This routine can only be utilized after the screen system* has been initialized.** Parameters:* operation Operation to perform** Returns:* Nothing**========================================================================*///void d_class( MARA_CFG * config, int operation )//{// int i, j, k;// int maxitr; /* Max number of definitions during update */// int opr;// abort_flag = FALSE;// if( operation == M_UPDATE )// {// opr = M_UPDATE;// d_class( config, M_PREDISPLAY ); /* Force display before update */// }// else// {// opr = M_DISPLAY;// clearscreen( );// }// i = 0; /* Set line 0 */// d_field( 0, i++, "Category definitions", D_NULL, 0, ( char * ) 0, TRUE, M_DISPLAY );// i++;// maxitr = ( operation == M_DISPLAY ) ? config->num_class : MAX_CLASS;// for( j = 0, k = 0; j < maxitr; j++ )// {// bool non_equestrian = FALSE;// d_field( 0 + k, i, "Cat:", D_USTRING, 2, ( char * ) config->team_class[j].abr, TRUE, opr );// if( ( config->team_class[j].abr[0] == config->nonequestrian_class_abr[0] )// && ( config->team_class[j].abr[1] == config->nonequestrian_class_abr[1] ) )// {// non_equestrian = TRUE;// }// d_field( 8 + k, i, ":", D_STRING, LEN_CLASS_NAME,// config->team_class[j].full_name, TRUE, opr );// if( !non_equestrian )// d_field( LEN_CLASS_NAME + 10 + k, i, "Start:", D_TIME, 8,// ( char * ) &config->team_class[j].start, TRUE, opr );// /*// ** Step to next column or row// */// k += 40;// if( !( ( j + 1 ) % 2 ) )// {// k = 0;// i++;// }// }//}/*========================================================================** Configuration Update and Display** Purpose:* This function is called to Configuration Update and Display** Parameters:* operation Operation to perform** Returns:* Nothing**========================================================================*///void d_config( MARA_CFG * config, int operation )//{// int i, j, k;// int maxitr; /* Max number of definitions during update */// int opr;// abort_flag = FALSE;// if( operation == M_UPDATE )// {// opr = M_UPDATE;// d_config( config, M_PREDISPLAY ); /* Force display before update */// }// else// {// opr = M_DISPLAY;// clearscreen( );// }// i = 0; /* Set line 0 */// d_field( 0, i++, "Marathon configuration", D_NULL, 0, ( char * ) 0, TRUE, M_DISPLAY );// d_field( 0, ++i, "Name: ", D_STRING, MAX_EVENT_NAME, config->event_name, TRUE, opr );// /*// * display the leg names// */// i += 2;// maxitr = ( operation == M_DISPLAY ) ? config->num_legs : MAX_LEGS;// for( j = 1; j <= maxitr; j++, i++ )// {// d_field( 0, i, "Leg ", D_NUMBER, 1, ( char * ) &j, TRUE, M_DISPLAY );// d_field( 6, i, ": ", D_STRING, MAX_LEG_NAME, config->leg_name[j - 1], TRUE, opr );// }// abort_flag = FALSE; /* Trap aborts at the next field */// /*// * Display the team break definitions// */// i++;// d_field( 0, i++, "Valid team numbers are in the following ranges", D_NULL,// 0, ( char * ) 0, TRUE, M_DISPLAY );// maxitr = ( operation == M_DISPLAY ) ? config->num_teams : MAX_TMS_SPLIT;// for( k = 0, j = 0; j < maxitr; j++ )// {// d_field( k + 0, i, "From ", D_NUMBER, 4, ( char * ) &config->t_def[j].start, TRUE, opr );// d_field( k + 9, i, " to ", D_NUMBER, 4, ( char * ) &config->t_def[j].end, TRUE, opr );// k += 20;// if( !( ( j + 1 ) % 4 ) )// {// k = 0;// i++;// }// }// /*// * Name of legend config->addendum file// */// abort_flag = FALSE;// i++;// d_field( 0, i++, "Legend addendum file :", D_STRING,// ( int ) sizeof( config->addendum ) - 1, ( char * ) config->addendum, TRUE, opr );// /*// * Name of the alternate data file// */// d_field( 0, i++, "Data filename :", D_STRING,// ( int ) sizeof( config->datafilename ) - 1,// ( char * ) config->datafilename, TRUE, opr );// /*// ** Non-equestrian configuration information// */// abort_flag = FALSE;// i++;// d_field( 0, i++, "Equestrian Leg :", D_NUMBER, 1, ( char * ) &config->equestrian_leg, TRUE, opr );// d_field( 0, i++, "Non-Equestrian Category :", D_USTRING,// ( int ) sizeof( config->nonequestrian_class_abr ) - 1,// ( char * ) config->nonequestrian_class_abr, TRUE, opr );// /*// ** Print control// */// abort_flag = FALSE;// i++;// d_field( 0, i, "Lines Per Page :", D_NUMBER, 3, ( char * ) &config->lines_per_page, TRUE, opr );// d_field( 30, i++, "Perf Skip :", D_NUMBER, 1, ( char * ) &config->perf_skip, TRUE, opr );//}/*========================================================================** Display the current country list** Purpose:* This function is called to Display the current country list** Parameters:* None** Returns:* Nothing**========================================================================*///void display_country( void )//{// d_cntry( &config, M_DISPLAY );// cur( 0, n_lines - 1 );// printf( "Any key to return to main menu :" );// ( void ) getinp( );//}/*========================================================================** Define a new entry in the county list** Purpose:* This function is called to Define a new entry in the county list** Parameters:* None** Returns:* Nothing**========================================================================*///void define_country( void )//{// int error;// ty_t_country *ptr;// int i;// /*// ** Copy working configuration into a temp structure for// ** use within the function// */// newcfg = config;// do// {// error = 0;// newcfg.num_countries = 0;// /*// * Get the operator to update the screen// */// d_cntry( &newcfg, M_UPDATE ); /* Update the country data */// printf( "" );// /*// * Now check the data that has been entered.// */// ptr = newcfg.country_name;// for( i = 0; i < MAX_COUNTRY; i++, ptr++ )// {// compact( ptr->abr );// compact( ptr->full_name );// if( ( ptr->abr[0] == '\0' ) != ( ptr->full_name[0] == '\0' ) )// {// error++;// printf( "Missing field" );// }// if( ptr->abr[0] )// newcfg.num_countries++;// }// if( error )// {// printf( "Configuration error - error must be corrected" );// printf( "Any key to continue " );// ( void ) getinp( );// }// else// {// printf( "Install configuration (Y)es, (D)iscard, (E)dit again :" );// switch ( getfnc( "*YDEA" ) )// {// case 'Y':// config = newcfg;// wt_config( ); /* Write out the data */// break;// case 'D':// break;// default:// error = TRUE;// break;// }// }// } while( error );// return;//}/*========================================================================** Display / Update Country list** Purpose:* This function is called to Display or Update Country list** Parameters:* operation Operation to perform** Returns:* Nothing**========================================================================*///void d_cntry( MARA_CFG * config, int operation )//{// int i, j, k;// int opr;// abort_flag = FALSE;// if( operation == M_UPDATE )// {// opr = M_UPDATE;// d_cntry( config, M_PREDISPLAY ); /* Force display before update */// }// else// {// opr = M_DISPLAY;// clearscreen( );// }// i = 0; /* Set line 0 */// d_field( 0, i++, "Country classifications", D_NULL, 0, ( char * ) 0, TRUE, M_DISPLAY );// /*// * Display the country names// */// i++;// for( j = 0, k = 0; j < MAX_COUNTRY; j++ )// {// d_field( 0 + k, i, "Country: ", D_STRING, 4,// ( char * ) config->country_name[j].abr, TRUE, opr );// d_field( 13 + k, i, ": ", D_STRING, LEN_CNTRY_NAME,// config->country_name[j].full_name, TRUE, opr );// k += 40;// if( !( ( j + 1 ) % 2 ) )// {// k = 0;// i++;// }// }//}/*========================================================================** Display the Winners List** Purpose:* This function is called to Display the current winners list** Parameters:* None** Returns:* Nothing**========================================================================*///void display_winners( void )//{// calc_class_summary( & class_summary );// d_winners( &config, M_DISPLAY );// cur( 0, n_lines - 1 );// printf( "Any key to return to main menu :" );// ( void ) getinp( );//}/*========================================================================** Update the winners information** Purpose:* This function is called to update the winners information** Parameters:* None** Returns:* Nothing**========================================================================*///bool define_winners( void )//{// int error;// int i;// bool changed = FALSE;// /*// ** Update the class summary info to give the user a hint// */// calc_class_summary( & class_summary );// /*// ** Copy working configuration into a temp structure for// ** use within the function// */// newcfg = config;// /*// ** Edit and sanity test the cnfig data until the user is happy// ** with it - or is ready to discard it.// */// do// {// error = 0;// d_winners ( &newcfg, M_UPDATE );// printf( "" );// /*// ** Sanity test of the data// */// for( i = 0; i < MAX_CLASS; i++ )// {// if( newcfg.team_class[i].abr[0] != '\0' && newcfg.class_winners[i] == 0 )// {// printf( " Warning: Class without winners: %s", newcfg.team_class[i].abr );// }// if ( newcfg.class_winners[i] > class_summary.teamclass[i+1].total )// {// printf( " Warning: Num winners greater than those in class: %s", newcfg.team_class[i].abr );// }// }// newcfg.num_fame = 0;// for( i = 0; i < MAX_FAME; i++ )// if( newcfg.hall_fame[i][0] )// newcfg.num_fame++;// for( i = newcfg.num_fame; i < MAX_FAME; i++ )// if( newcfg.hall_fame[i][0] )// {// printf( "Configuration error: Missing Fame name. Gaps not allowed" );// error++;// break;// }// abort_flag = FALSE;// if( error )// {// printf( "Any key to continue " );// getinp( );// }// else// {// printf( "Install configuration (Y)es, (D)iscard, (E)dit again :" );// switch ( getfnc( "*YDEA" ) )// {// case 'Y':// config = newcfg;// wt_config( );// changed = TRUE;// break;// case 'D':// break;// default:// error = TRUE;// break;// }// }// } while( error && ! abort_flag );// return ( changed );//}/*========================================================================** Display / Update winners list** Purpose:* This function is called to Display or Update winners list** Parameters:* operation Operation to perform** Returns:* Nothing**========================================================================*///void d_winners( MARA_CFG * config, int operation )//{// int i, j, k;// int maxitr; /* Max number of definitions during update */// int opr;// abort_flag = FALSE;// if( operation == M_UPDATE )// {// opr = M_UPDATE;// d_winners( config, M_PREDISPLAY ); /* Force display before update */// }// else// {// opr = M_DISPLAY;// clearscreen( );// }// i = 0; /* Set line 0 */// d_field( 0, i++, "Winner definitions", D_NULL, 0, ( char * ) 0, TRUE, M_DISPLAY );// i++;// maxitr = config->num_class;// for( j = 0, k = 0; j < maxitr; j++ )// {// d_field( 0 + k, i, "Cat:", D_USTRING, 2, ( char * ) config->team_class[j].abr, TRUE, M_DISPLAY );// d_field( 7 + k, i, ":", D_STRING, LEN_CLASS_NAME,// config->team_class[j].full_name, TRUE, M_DISPLAY );// d_field( LEN_CLASS_NAME + 9 + k, i, "Num:", D_NUMBER, 3,// ( char * ) &class_summary.teamclass[j+1].total, TRUE, M_DISPLAY );// d_field( LEN_CLASS_NAME + 9 + 7 + k, i, "Win:", D_NUMBER, 3,// ( char * ) &config->class_winners[j], TRUE, opr );// /*// ** Step to next column or row// */// k += 40;// if( !( ( j + 1 ) % 2 ) )// {// k = 0;// i++;// }// }// abort_flag = FALSE;// i += 2;// d_field( 0, i++, "Hall of Fame", D_NULL, 0, ( char * ) 0, TRUE, M_DISPLAY );// for( j = 0, k = 0; j < MAX_FAME; j++ )// {// d_field( k, i, "Name : ", D_STRING, MAX_PERSON_NAME,// &config->hall_fame[j], TRUE, opr );// k += 40;// if( !( ( j + 1 ) % 2 ) )// {// k = 0;// i++;// }// }//}/*========================================================================** Read in the configuration file** Purpose:* This function is called to read in the configuration file** Parameters:* None** Returns:* Nothing**========================================================================*/bool rd_config( void ){FILE *fcon;int ok;fcon = fopen( confile, "rb" );if( ! fcon ){printf( "Configuration file %s not found", confile );return ( FALSE );}ok = r_config( fcon );fclose( fcon );return ( ok );}/*========================================================================** Read in the configuration file** Purpose:* This function is called to read in the configuration file* NOTE: Must be maintained with the Writer function** Parameters:* fcon File number of the config file** Returns:* FALSE if an error is encountered**========================================================================*/bool r_config( FILE *fcon ){int len; /* Length of data read *//** Event name*/printf( "Reading: Event Name" );len = fread( config.event_name, sizeof( config.event_name ), 1 , fcon );if( len != 1 )return ( FALSE );/** Leg names*/printf( "Reading: Leg Names" );len = fread( config.leg_name, sizeof( config.leg_name ), 1 , fcon );if( len != 1 )return ( FALSE );/** Team definitions*/printf( "Reading: Team Defs" );len = fread( config.t_def, sizeof( config.t_def ), 1 , fcon );if( len != 1 )return ( FALSE );/** Number of legs*/printf( "Reading: Leg Nums" );len = fread( &config.num_legs, sizeof( config.num_legs ), 1 , fcon );if( len != 1)return ( FALSE );/** Number of team splits*/printf( "Reading: Team Splits" );len = fread( &config.num_teams, sizeof( config.num_teams ), 1 , fcon );if( len != 1 )return ( FALSE );config.min_team = config.t_def[0].start;config.max_team = config.t_def[config.num_teams - 1].end;/** Class information*/printf( "Reading: Class Data" );len = fread( config.team_class, sizeof( config.team_class ), 1 , fcon );if( len != 1 )return ( FALSE );len = fread( &config.num_class, sizeof( config.num_class ), 1 , fcon );if( len != 1 )return ( FALSE );/** Country list*/printf( "Reading: Country Data, Name" );len = fread( config.country_name, sizeof( config.country_name ), 1 , fcon );if( len != 1 )return ( FALSE );printf( "Reading: Country Data, Number" );len = fread( &config.num_countries, sizeof( config.num_countries ), 1 , fcon );if( len != 1 )return ( FALSE );/** Addendum file*/printf( "Reading: Addendum File" );len = fread( config.addendum, sizeof( config.addendum ), 1 , fcon );if( len != 1 )return ( feof( fcon ) );/** Name of the data file*/printf( "Reading: Name of data file" );len = fread( config.datafilename, sizeof( config.datafilename ) , 1 , fcon );if( len != 1 )return ( feof( fcon ) );/*** Non-equestrian configuration information*/printf( "Reading: NonEquest" );len = fread( config.nonequestrian_class_abr, sizeof( config.nonequestrian_class_abr ), 1 , fcon );if( len != 1 )return ( feof( fcon ) );printf( "Reading: NonEquest-2" );len = fread( &config.equestrian_leg, sizeof( config.equestrian_leg ), 1 , fcon );if( len != 1 )return ( FALSE );/*** .txt file output control. Lines per page and perf-skipping*/printf( "Reading: Output Control" );len = fread( &config.lines_per_page, sizeof( config.lines_per_page ), 1 , fcon );if( len != 1 )return ( feof( fcon ) );printf( "Reading: Output Control-2" );len = fread( &config.perf_skip, sizeof( config.perf_skip ), 1 , fcon );if( len != 1 )return ( FALSE );printf( "Reading: Winners Info" );len = fread( &config.class_winners, sizeof( config.class_winners ), 1 , fcon );if( len != 1 )return ( FALSE );printf( "Reading: Hall of Fame Info" );len = fread( &config.hall_fame, sizeof( config.hall_fame ), 1 , fcon );if( len != 1 )return ( FALSE );printf( "Reading: Hall of Fame Numbers" );len = fread( &config.num_fame, sizeof( config.num_fame ), 1 , fcon );if( len != 1 )return ( feof( fcon ) );return ( TRUE );}/*========================================================================** Write out the configuration file** Purpose:* This function is called to write the configuration file* NOTE: Must be maintained with the Reader function** Parameters:* None** Returns:* FALSE : Error encountered**========================================================================*/bool wt_config( void ){FILE *fcon;/*** Open as a binary file*/fcon = fopen( confile, "wb" );if( !fcon )return ( FALSE );/*** Write out multiple structures** Event name** Leg names** Team definitions** Number of legs** Number fo team splits** Class information** Number of defined classes** Country list** Number of defined countries** Legend config.addendum file name** Data file name*/fwrite( config.event_name, sizeof( config.event_name ), 1, fcon );fwrite( config.leg_name, sizeof( config.leg_name ), 1, fcon );fwrite( config.t_def, sizeof( config.t_def ), 1, fcon );fwrite( &config.num_legs, sizeof( config.num_legs ), 1, fcon );fwrite( &config.num_teams, sizeof( config.num_teams ), 1, fcon );fwrite( config.team_class, sizeof( config.team_class ), 1, fcon );fwrite( &config.num_class, sizeof( config.num_class ), 1, fcon );fwrite( config.country_name, sizeof( config.country_name ), 1, fcon );fwrite( &config.num_countries, sizeof( config.num_countries ), 1, fcon );fwrite( config.addendum, sizeof( config.addendum ), 1, fcon );fwrite( config.datafilename, sizeof( config.datafilename ), 1, fcon );fwrite( config.nonequestrian_class_abr, sizeof( config.nonequestrian_class_abr ), 1, fcon );fwrite( &config.equestrian_leg, sizeof( config.equestrian_leg ), 1, fcon );fwrite( &config.lines_per_page, sizeof( config.lines_per_page ), 1, fcon );fwrite( &config.perf_skip, sizeof( config.perf_skip ), 1, fcon );fwrite( &config.class_winners, sizeof( config.class_winners ), 1, fcon );fwrite( &config.hall_fame, sizeof( config.hall_fame ), 1, fcon );fwrite( &config.num_fame, sizeof( config.num_fame ), 1, fcon );fclose( fcon );return ( TRUE );}/*========================================================================** Qsort callback: Sort by team** Purpose:* Function used by the team definition sort operation* It will compare two entries of the team def structure and return an* integer for gt eq lt conditions.* Note : If the start is 0 the team entry does exist and is placed at the* end of the sorted list.** Parameters:* a comparision entry* b comparision entry** Returns:* gt, eq, lt as required**========================================================================*/int f_comp_int( const void *aa, const void *bb ){const ty_t_def *a = (ty_t_def *)aa;const ty_t_def *b = (ty_t_def *)bb;if( a->start == 0 )return ( 1 );else if( b->start == 0 )return ( -1 );elsereturn ( a->start - b->start );}/*========================================================================** Compact a string** Purpose:* This function is called remove leading and trailing spaces from* a string. Treats other non-printing characters as leading* spaces. This solves a problem when importing data from a* Microsoft CSV file with empty fields.** Parameters:* str Address of the string to compact** Returns:* Nothing**========================================================================*/void compact( char *str ){char *ptr;ptr = str;while( *str && ( isspace( *str ) || !isprint( *str ) ) )str++;strcpy( ptr, str );}/*========================================================================** Validate a team number** Purpose:* This function is called to validate a team number** Parameters:* x Number to validate** Returns:* TRUE : Valid* FALSE : Not valid**========================================================================*/bool valid_field( int x ){int i;for( i = 0; i < config.num_teams; i++ ){if( x <= config.t_def[i].end && x >= config.t_def[i].start )return ( TRUE );if( x < config.t_def[i].start )break; /* Because the list is sorted */}return ( FALSE );}/*========================================================================** Get a class descriptor from existing text** Purpose:* This function is called to Get a class descriptor** Parameters:* text - User text to examine* config - configuration dtaa to use** Returns:* An integer which is the index into the config.team_class array* The integer is in the range 1 .. num_class* A value fo zero indicates the text was not found.**========================================================================*/int lookup_class( const char *text, MARA_CFG * config_ptr ){int i;if( config_ptr == NULL )config_ptr = &config;/** Attempt to locate the entered class in the list of defined classes*/for( i = 0; i < config_ptr->num_class; i++ ){if( toupper(text[0]) == toupper(config_ptr->team_class[i].abr[0]) &&toupper(text[1]) == toupper(config_ptr->team_class[i].abr[1]) )return ( ++i );}return ( 0 );}/********************************* EOF ***********************************/