/*****************************************************************************
* PARSE_A.C
*
*      ANSI stubs / replacements for the UNICODE command line parsing 
*      routines (parse.c)
*
*      External Entry Points:  (defined in utilsub.h)
*
*         ParseCommandLineA()
*         IsTokenPresentA()
*         SetTokenPresentA()
*         SetTokenNotPresentA()
*
* Copyright Citrix Systems Inc. 1995
* Copyright (C) 1997-1999 Microsoft Corp.
*
*   $Author:   butchd  $ Butch Davis
****************************************************************************/

/* Get the standard C includes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

#include <winstaw.h>
#include <utilsub.h>

/*=============================================================================
 ==   Local Functions Defined
 ============================================================================*/

/*=============================================================================
 ==   External Functions Used
 ============================================================================*/

/*=============================================================================
 ==   Local Variables Used
 ============================================================================*/

/*=============================================================================
 ==   Global Variables Used
 ============================================================================*/

/*****************************************************************************
*
*   ParseCommandLineA (ANSI stub for ParseCommandLineW)
*
*   Thunks over argv_a (ANSI) to argv_w (UNICODE) and TOKMAPA to TOKMAPW, 
*   calls ParseCommandLineW(), then thunks back TOKMAPW to TOKMAPA and
*   returns
*
*   ENTRY:
*       (refer to ParseCommandLineW)
*   EXIT:
*       (refer to ParseCommandLineW), plus
*       PARSE_FLAG_NOT_ENOUGH_MEMORY
*
****************************************************************************/

#define tmFormIsString(x) ((x == TMFORM_S_STRING) || (x == TMFORM_DATE) || (x == TMFORM_PHONE) || (x == TMFORM_STRING) || (x == TMFORM_X_STRING))

USHORT WINAPI
ParseCommandLineA( INT argc,
                   CHAR **argv_a,
                   PTOKMAPA ptm_a,
                   USHORT flag )
{
    int i, len1, len2;
    USHORT rc = PARSE_FLAG_NOT_ENOUGH_MEMORY;   // default to memory error
    WCHAR **argv_w = NULL;
    PTOKMAPA ptmtmp_a;
    PTOKMAPW ptmtmp_w, ptm_w = NULL;

    /*
     * If no parameters, we skip a lot of work.
     */
    if ( argc == 0 ) {
        rc = PARSE_FLAG_NO_PARMS;
        return(rc);
    }

    /*        
     * Alloc and form WCHAR argvw array.
     */
    if ( !(argv_w = (WCHAR **)malloc( (len1 = argc * sizeof(WCHAR *)) )) )
        goto done;  // memory error
    memset(argv_w, 0, len1);     // zero all to init pointers to NULL
    for ( i = 0; i < argc; i++ ) {
        if ( argv_w[i] = malloc((len1 = ((len2 = strlen(argv_a[i])+1) * 2))) ) {
            memset(argv_w[i], 0, len1);
            mbstowcs(argv_w[i], argv_a[i], len2);
        } else {
            goto done;  // memory error
        }
    }

    /*
     * Alloc and form TOKMAPW array.
     */
    for ( ptmtmp_a=ptm_a, i=0; 
          ptmtmp_a->tmToken != NULL; 
          ptmtmp_a++, i++ );
    if ( !(ptm_w = (PTOKMAPW)malloc( (len1 = ++i * sizeof(TOKMAPW)) )) )
        goto done;  // memory error
    memset(ptm_w, 0, len1);     // zero all to init pointers to NULL
    for ( ptmtmp_w=ptm_w, ptmtmp_a=ptm_a;
          ptmtmp_a->tmToken != NULL; 
          ptmtmp_w++, ptmtmp_a++ ) {

        /*                
         * Allocate and convert token.
         */
        if ( ptmtmp_w->tmToken = 
                malloc((len1 = ((len2 = strlen(ptmtmp_a->tmToken)+1) * 2))) ) {
            memset(ptmtmp_w->tmToken, 0, len1);
            mbstowcs(ptmtmp_w->tmToken, ptmtmp_a->tmToken, len2);
        } else {
            goto done;  // memory error
        }

        /*
         * Copy flag, form, and length (no conversion needed).
         */
        ptmtmp_w->tmFlag = ptmtmp_a->tmFlag;
        ptmtmp_w->tmForm = ptmtmp_a->tmForm;
        ptmtmp_w->tmDLen = ptmtmp_a->tmDLen;

        /*
         * Allocate or copy address if a data length was specified.
         */
        if ( ptmtmp_w->tmDLen ) {

            /*
             * Allocate new WCHAR address if we're a string type.  
             * Otherwise, point to original address (no conversion needed).
             */
            if ( tmFormIsString(ptmtmp_w->tmForm) ) {

                if ( ptmtmp_w->tmAddr =
                        malloc(len1 = ptmtmp_w->tmDLen*sizeof(WCHAR)) )
                    memset(ptmtmp_w->tmAddr, 0, len1);
                else
                    goto done;  // memory error

            } else {

                ptmtmp_w->tmAddr = ptmtmp_a->tmAddr;
            }

            /*
             * For proper default behavior, zero ANSI address contents if 
             * the "don't clear memory" flag is not set.
             */
            if ( !(flag & PCL_FLAG_NO_CLEAR_MEMORY) )
                memset(ptmtmp_a->tmAddr, 0, ptmtmp_a->tmDLen);
        }
    }

    /*
     * Call ParseCommandLineW
     */
    rc = ParseCommandLineW(argc, argv_w, ptm_w, flag);

    /*
     * Copy flags for each TOPMAPW element.  Also, convert to ANSI strings
     * that were present on the command line into caller's TOKMAPA array, if 
     * data length was specified.
     */
    for ( ptmtmp_w=ptm_w, ptmtmp_a=ptm_a;
          ptmtmp_w->tmToken != NULL; 
          ptmtmp_w++, ptmtmp_a++ ) {

        ptmtmp_a->tmFlag = ptmtmp_w->tmFlag;

        if ( ptmtmp_w->tmDLen && 
             (ptmtmp_w->tmFlag & TMFLAG_PRESENT) &&
             tmFormIsString(ptmtmp_w->tmForm) )
            wcstombs(ptmtmp_a->tmAddr, ptmtmp_w->tmAddr, ptmtmp_w->tmDLen);
    }

done:
    /*
     * Free the argvw array.
     */
    if ( argv_w ) {

        for ( i = 0; i < argc; i++ ) {
            if ( argv_w[i] )
                free(argv_w[i]);
        }
        free(argv_w);
    }

    /*
     * Free the TOKMAPW tokens, string addresses, and TOKMAK array itself.
     */
    if ( ptm_w ) {

        for ( ptmtmp_w=ptm_w; ptmtmp_w->tmToken != NULL; ptmtmp_w++ ) {

            /*                
             * Free token.
             */
            free(ptmtmp_w->tmToken);

            /*
             * Free address if a data length was specified and we're a
             * string type.
             */
            if ( ptmtmp_w->tmDLen && tmFormIsString(ptmtmp_w->tmForm) )
                free(ptmtmp_w->tmAddr);
        }
        free(ptm_w);
    }

    /*
     * Return ParseCommandLineW status.
     */
    return(rc);

}  // end ParseCommandLineA


/*****************************************************************************
*
*   IsTokenPresentA (ANSI version)
*
*       Determines if a specified command line token (in given TOKMAPA array)
*       was present on the command line.
*
*   ENTRY:
*       ptm (input)
*           Points to 0-terminated TOKMAPA array to scan.
*       pToken (input)
*           The token to scan for.
*
*   EXIT:
*       TRUE if the specified token was present on the command line;
*       FALSE otherwise.
*
****************************************************************************/

BOOLEAN WINAPI
IsTokenPresentA( PTOKMAPA ptm,
                 PCHAR pToken )
{
    int i;

    for ( i = 0; ptm[i].tmToken; i++ ) {
        if ( !strcmp( ptm[i].tmToken, pToken ) )
            return( (ptm[i].tmFlag & TMFLAG_PRESENT) ? TRUE : FALSE );
    }

    return(FALSE);

}  // end IsTokenPresentA


/*****************************************************************************
*
*   SetTokenPresentA (ANSI version)
*
*       Forces a specified command line token (in given TOKMAPA array)
*       to be flagged as 'present' on the command line.
*
*   ENTRY:
*       ptm (input)
*           Points to 0-terminated TOKMAPA array to scan.
*       pToken (input)
*           The token to scan for and set flags.
*
*   EXIT:
*       TRUE if the specified token was found in the TOKMAPA array
*       (TMFLAG_PRESENT flag is set).  FALSE otherwise.
*
****************************************************************************/

BOOLEAN WINAPI
SetTokenPresentA( PTOKMAPA ptm,
                  PCHAR pToken )
{
    int i;

    for ( i = 0; ptm[i].tmToken; i++ ) {
        if ( !strcmp( ptm[i].tmToken, pToken ) ) {
            ptm[i].tmFlag |= TMFLAG_PRESENT;
            return(TRUE);
        }
    }

    return(FALSE);

}  // end SetTokenPresentA


/*****************************************************************************
*
*   SetTokenNotPresentA (ANSI Versio)
*
*       Forces a specified command line token (in given TOKMAPA array)
*       to be flagged as 'not present' on the command line.
*
*   ENTRY:
*       ptm (input)
*           Points to 0-terminated TOKMAPA array to scan.
*       pToken (input)
*           The token to scan for and set flags.
*
*   EXIT:
*       TRUE if the specified token was found in the TOKMAPA array
*       (TMFLAG_PRESENT flag is reset).  FALSE otherwise.
*
****************************************************************************/

BOOLEAN WINAPI
SetTokenNotPresentA( PTOKMAPA ptm,
                     PCHAR pToken )
{
    int i;

    for ( i = 0; ptm[i].tmToken; i++ ) {
        if ( !strcmp( ptm[i].tmToken, pToken ) ) {
            ptm[i].tmFlag &= ~TMFLAG_PRESENT;
            return(TRUE);
        }
    }

    return(FALSE);

}  // end SetTokenNotPresentA