/************************************************************************* * 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" ); return true; 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 ); else return ( 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 ***********************************/