// MyTapi.cpp: My TAPI helper function implementations

#include "stdafx.h"
#include "MyTapi.h"

///////////////////////////////////////////////////////////////////////////
// LINEDEVCAPS wrappers

// Caller responsible for freeing returned memory
LONG MyGetLineDevCaps(
    HLINEAPP      hLineApp,
    DWORD         nApiVersion,
    DWORD         nLineID,
    LINEDEVCAPS** ppd)
{
    DWORD dwNeededSize = sizeof(LINEDEVCAPS);
    LONG  tr = 0;

    do
    {
        // Get some more memory if we don't have enough
        if( !*ppd || (*ppd)->dwTotalSize < dwNeededSize )
        {
            *ppd = (LPLINEDEVCAPS)::realloc(*ppd,
                                            dwNeededSize);
            if( *ppd )
            {
                (*ppd)->dwTotalSize = dwNeededSize;
            }
            else
            {
                return LINEERR_NOMEM;
            }
        }

        // Fill in the buffer
        tr = lineGetDevCaps(hLineApp, nLineID, nApiVersion, 0, *ppd);

        // Check how much memory we need
        // (some TSPs succeed even if the
        //  data size is too small)
        if( tr == LINEERR_STRUCTURETOOSMALL ||
            (tr == 0 &&
             (*ppd)->dwTotalSize < (*ppd)->dwNeededSize) )
        {
            dwNeededSize = (*ppd)->dwNeededSize;
            tr = LINEERR_STRUCTURETOOSMALL;
        }
    }
    while( tr == LINEERR_STRUCTURETOOSMALL );

    return tr;
}

LPCSTR MyGetLineName(
    LINEDEVCAPS*    pd)
{
    ASSERT(pd);
    return (pd->dwLineNameSize ? (LPCSTR)(BYTE*)pd + pd->dwLineNameOffset : "");
}

///////////////////////////////////////////////////////////////////////////
// LINECOUNTRYLIST wrappers

// Caller responsible for freeing returned memory
LONG MyGetCountryList(
    DWORD               nApiVersion,
    DWORD               nCountryID,
    LINECOUNTRYLIST**   ppd)
{
    DWORD dwNeededSize = sizeof(LINECOUNTRYLIST);
    LONG  tr = 0;

    do
    {
        // Get some more memory if we don't have enough
        if( !*ppd || (*ppd)->dwTotalSize < dwNeededSize )
        {
            *ppd = (LPLINECOUNTRYLIST)::realloc(*ppd,
                                            dwNeededSize);
            if( *ppd )
            {
                (*ppd)->dwTotalSize = dwNeededSize;
            }
            else
            {
                return LINEERR_NOMEM;
            }
        }

        // Fill in the buffer
        tr = lineGetCountry(nCountryID, nApiVersion, *ppd);

        // Check how much memory we need
        // (some TSPs succeed even if the
        //  data size is too small)
        if( tr == LINEERR_STRUCTURETOOSMALL ||
            (tr == 0 &&
             (*ppd)->dwTotalSize < (*ppd)->dwNeededSize) )
        {
            dwNeededSize = (*ppd)->dwNeededSize;
            tr = LINEERR_STRUCTURETOOSMALL;
        }
    }
    while( tr == LINEERR_STRUCTURETOOSMALL );

    return tr;
}

DWORD MyGetCountryCode(
    LINECOUNTRYLIST*    pd,
    DWORD               nCountry)
{
    ASSERT(pd);
    ASSERT(nCountry < pd->dwNumCountries);
    LPLINECOUNTRYENTRY  alce = (LPLINECOUNTRYENTRY)((BYTE*)pd + pd->dwCountryListOffset);
    ASSERT(alce);

    return alce[nCountry].dwCountryCode;
}

LPCSTR MyGetCountryName(
    LINECOUNTRYLIST*    pd,
    DWORD               nCountry)
{
    ASSERT(pd);
    ASSERT(nCountry < pd->dwNumCountries);
    LPLINECOUNTRYENTRY  alce = (LPLINECOUNTRYENTRY)((BYTE*)pd + pd->dwCountryListOffset);
    ASSERT(alce);

    return (alce[nCountry].dwCountryNameSize
            ? (LPCSTR)(BYTE*)pd + alce[nCountry].dwCountryNameOffset : "");
}

///////////////////////////////////////////////////////////////////////////
// LINETRANSLATECAPS wrappers

// Caller responsible for freeing returned memory
LONG MyGetTranslateCaps(
    HLINEAPP            hLineApp,
    DWORD               nApiVersion,
    LINETRANSLATECAPS** ppd)
{
    DWORD dwNeededSize = sizeof(LINETRANSLATECAPS);
    LONG  tr = 0;

    do
    {
        // Get some more memory if we don't have enough
        if( !*ppd || (*ppd)->dwTotalSize < dwNeededSize )
        {
            *ppd = (LPLINETRANSLATECAPS)::realloc(*ppd,
                                            dwNeededSize);
            if( *ppd )
            {
                (*ppd)->dwTotalSize = dwNeededSize;
            }
            else
            {
                return LINEERR_NOMEM;
            }
        }

        // Fill in the buffer
        tr = lineGetTranslateCaps(hLineApp, nApiVersion, *ppd);

        // Check how much memory we need
        // (some TSPs succeed even if the
        //  data size is too small)
        if( tr == LINEERR_STRUCTURETOOSMALL ||
            (tr == 0 &&
             (*ppd)->dwTotalSize < (*ppd)->dwNeededSize) )
        {
            dwNeededSize = (*ppd)->dwNeededSize;
            tr = LINEERR_STRUCTURETOOSMALL;
        }
    }
    while( tr == LINEERR_STRUCTURETOOSMALL );

    return tr;
}

LPCSTR MyGetLocationName(
    LINETRANSLATECAPS*  pd,
    DWORD               nLocation)
{
    ASSERT(pd);
    ASSERT(nLocation < pd->dwNumLocations);
    LPLINELOCATIONENTRY   alle = (LPLINELOCATIONENTRY)((BYTE*)pd + pd->dwLocationListOffset);
    ASSERT(alle);

    return (alle[nLocation].dwLocationNameSize
            ? (LPCSTR)(BYTE*)pd + alle[nLocation].dwLocationNameOffset : "");
}

DWORD MyGetPermanentLocationID(
    LINETRANSLATECAPS*  pd,
    DWORD               nLocation)
{
    ASSERT(pd);
    ASSERT(nLocation < pd->dwNumLocations);
    LPLINELOCATIONENTRY   alle = (LPLINELOCATIONENTRY)((BYTE*)pd + pd->dwLocationListOffset);
    ASSERT(alle);

    return alle[nLocation].dwPermanentLocationID;
}

///////////////////////////////////////////////////////////////////////////
// LINEADDRESSCAPS wrappers

// Caller responsible for freeing returned memory
LONG MyGetAddressCaps(
    HLINEAPP            hLineApp,
    DWORD               nLineID,
    DWORD               nAddressID,
    DWORD               nApiVersion,
    LINEADDRESSCAPS**   ppd)
{
    DWORD dwNeededSize = sizeof(LINEADDRESSCAPS);
    LONG  tr = 0;

    do
    {
        // Get some more memory if we don't have enough
        if( !*ppd || (*ppd)->dwTotalSize < dwNeededSize )
        {
            *ppd = (LPLINEADDRESSCAPS)::realloc(*ppd,
                                            dwNeededSize);
            if( *ppd )
            {
                (*ppd)->dwTotalSize = dwNeededSize;
            }
            else
            {
                return LINEERR_NOMEM;
            }
        }

        // Fill in the buffer
        tr = lineGetAddressCaps(hLineApp, nLineID, nAddressID, nApiVersion, 0, *ppd);

        // Check how much memory we need
        // (some TSPs succeed even if the
        //  data size is too small)
        if( tr == LINEERR_STRUCTURETOOSMALL ||
            (tr == 0 &&
             (*ppd)->dwTotalSize < (*ppd)->dwNeededSize) )
        {
            dwNeededSize = (*ppd)->dwNeededSize;
            tr = LINEERR_STRUCTURETOOSMALL;
        }
    }
    while( tr == LINEERR_STRUCTURETOOSMALL );

    return tr;
}

LPCSTR MyGetAddress(
    LINEADDRESSCAPS*    pd)
{
    ASSERT(pd);
    return (pd->dwAddressSize ? (LPCSTR)(BYTE*)pd + pd->dwAddressOffset : "");
}

///////////////////////////////////////////////////////////////////////////
// LINETRANSLATEOUTPUT wrappers

// Caller responsible for freeing returned memory
LONG MyTranslateAddress(
    HLINEAPP                hLineApp,
    DWORD                   nLineID,
    DWORD                   nApiVersion,
    LPCSTR                  pszAddressIn,
    LINETRANSLATEOUTPUT**   ppd)

{
    DWORD dwNeededSize = sizeof(LINETRANSLATEOUTPUT);
    LONG  tr = 0;

    do
    {
        // Get some more memory if we don't have enough
        if( !*ppd || (*ppd)->dwTotalSize < dwNeededSize )
        {
            *ppd = (LPLINETRANSLATEOUTPUT)::realloc(*ppd,
                                            dwNeededSize);
            if( *ppd )
            {
                (*ppd)->dwTotalSize = dwNeededSize;
            }
            else
            {
                return LINEERR_NOMEM;
            }
        }

        // Fill in the buffer
        tr = lineTranslateAddress(hLineApp, nLineID, nApiVersion, pszAddressIn, 0, 0, *ppd);

        // Check how much memory we need
        // (some TSPs succeed even if the
        //  data size is too small)
        if( tr == LINEERR_STRUCTURETOOSMALL ||
            (tr == 0 &&
             (*ppd)->dwTotalSize < (*ppd)->dwNeededSize) )
        {
            dwNeededSize = (*ppd)->dwNeededSize;
            tr = LINEERR_STRUCTURETOOSMALL;
        }
    }
    while( tr == LINEERR_STRUCTURETOOSMALL );

    return tr;
}

LPCSTR MyGetDisplayableString(
    LINETRANSLATEOUTPUT*    pd)
{
    ASSERT(pd);
    return (pd->dwDisplayableStringSize ? (LPCSTR)(BYTE*)pd + pd->dwDisplayableStringOffset : "");
}

