Subversion Repositories svn1-original

Rev

Rev 164 | 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" );

    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 ***********************************/