/***************************************************************************
 *                                                                         *
 *  MODULE      : huge.c                                                   *
 *                                                                         *
 *  PURPOSE     : This contains functions useful for generating and        *
 *                verifying huge text data blocks.                         *
 *                                                                         *
 ***************************************************************************/

#include "ddemlcl.h"
#include <string.h>
#include <stdio.h>
#include "huge.h"

extern DWORD idInst;
#define BUFSZ   435

LONG lseed, lmult, ladd;
char szT[BUFSZ];

VOID SetMyRand(LONG seed, LONG mult, LONG add);
char MyRand(VOID);
BOOL RandTest(LONG length, LONG seed, LONG mult, LONG add);

/****************************************************************************
 *                                                                          *
 *  FUNCTION   : SetMyRand()                                                *
 *                                                                          *
 *  PURPOSE    : Transfers random sequence generation variables to globals. *
 *                                                                          *
 ****************************************************************************/
VOID SetMyRand(
LONG seed,
LONG mult,
LONG add)
{
    lseed = seed;
    lmult = mult;
    ladd = add;
}


/****************************************************************************
 *                                                                          *
 *  FUNCTION   : MyRand()                                                   *
 *                                                                          *
 *  PURPOSE    : Generates the next random character in a sequence.         *
 *                                                                          *
 *  RETURNS    : the character generated                                    *
 *                                                                          *
 ****************************************************************************/
char MyRand()
{
    char c;

    lseed = lseed * lmult + ladd;
    c = (char)(LOWORD(lseed) ^ HIWORD(lseed));
    return((char)((c & (char)0x4f) + ' '));   // 0x20 - 0x6f - all printable
}


/*
 * This function allocates and fills a HUGE data handle with a verifiable
 * text string.
 *
 * The format of the text string is:
 * "<length>=<seed>*<mult>+<add>;---data of length <length>---\0"
 * all values are stored in base 16 numbers.
 */
/****************************************************************************
 *                                                                          *
 *  FUNCTION   : CreateHugeDataHandle()                                     *
 *                                                                          *
 *  PURPOSE    : Generates a huge pseudo-random sequence of printable       *
 *               characters of the length given and places then into        *
 *               a DDEML data handle.                                       *
 *                                                                          *
 *  RETURNS    : The data handle created or 0 on failure.                   *
 *                                                                          *
 ****************************************************************************/
HDDEDATA CreateHugeDataHandle(
LONG length,
LONG seed,
LONG mult,
LONG add,
HSZ hszItem,
WORD wFmt,
WORD afCmd)
{
    register WORD cb;
    HDDEDATA hData;
    DWORD cbData;
    char *psz;

    wsprintf(szT, "%ld=%ld*%ld+%ld;", length, seed, mult, add);
    cb = strlen(szT);
    hData = DdeCreateDataHandle(idInst, szT, cb + 1, 0, hszItem, wFmt, afCmd);
    if (hData)
        hData = DdeAddData(hData, NULL, 0, cb + length + 1);
    cbData = cb;
    SetMyRand(seed, mult, add);
    while (hData && (length > 0)) {
        psz = szT;
        cb = BUFSZ;
        while (cb--)
            *psz++ = MyRand();
        hData = DdeAddData(hData, szT, min(length, BUFSZ), cbData);
        cbData += BUFSZ;
        length -= BUFSZ;
    }
    return(hData);
}

/****************************************************************************
 *                                                                          *
 *  FUNCTION   : CheckHugeData()                                            *
 *                                                                          *
 *  PURPOSE    : Verifies the correctness of a pseudo-random character      *
 *               sequence generated by CreateHugeData.                      *
 *                                                                          *
 *  RETURNS    : TRUE if verified ok, FALSE otherwise.                      *
 *                                                                          *
 ****************************************************************************/
BOOL CheckHugeData(
HDDEDATA hData)
{
    LONG length;
    LONG seed;
    LONG mult;
    LONG add;
    char *psz;
    DWORD cbOff;
    WORD cb;

    if (!DdeGetData(hData, szT, BUFSZ, 0))
        return(FALSE);
    szT[BUFSZ - 1] = '\0';
    psz = strchr(szT, ';');
    if (psz == NULL)
        return(FALSE);
    *psz = '\0';

    if (sscanf(szT, "%ld=%ld*%ld+%ld", &length, &seed, &mult, &add) != 4)
        return(FALSE);

    if (length < 0)
        return(FALSE);
    SetMyRand(seed, mult, add);
    cbOff = strlen(szT) + 1;
    while (length > 0) {
        DdeGetData(hData, szT, BUFSZ, cbOff);
        psz = szT;
        cb = BUFSZ;
        while (length-- && cb--)
            if (*psz++ != MyRand())
                return(FALSE);
        cbOff += BUFSZ;
        length -= BUFSZ;
    }
    return(TRUE);
}

#if 0
/****************************************************************************
 *                                                                          *
 *  FUNCTION   : RandTest()                                                 *
 *                                                                          *
 *  PURPOSE    : Verifies the correctness of CreateHugeDataHandle() and     *
 *               CheckHugeData().                                           *
 *                                                                          *
 *  RETURNS    :                                                            *
 *                                                                          *
 ****************************************************************************/
BOOL RandTest(
LONG length,
LONG seed,
LONG mult,
LONG add)
{
    HDDEDATA hData;
    BOOL fSuccess;

    hData = CreateHugeDataHandle(length, seed, mult, add, 0, 1, 0);
    if (!hData)
        return(FALSE);
    fSuccess = CheckHugeData(hData);
    DdeFreeDataHandle(hData);
    return(fSuccess);
}
#endif
