#include <pro_ext.h>
#include <i86.h>

typedef unsigned short  USHORT;
typedef unsigned char   TEXT;

#define LoWord(x)       ((USHORT)x)                             // Low order of a word
#define HiWord(x)       ((USHORT)((unsigned long)(x)>>16))      // High order


/*----------------------------------------------------------------------+
 |  This function will update the values of the API copy of _PDPARMS    |
 |  with the current values of _PDPARMS.  It takes two optional         |
 |  arguments.  The first argument if supplied marks the first element  |
 |  number in the _PDPARMS to start updating. If this is the only       |
 |  parameter, then this is the only element updated.  If there is a    |
 |  second parameter, then this combined with the first argument will   |
 |  make up the scope of elements that will be updated.  If no arguments|
 |  are supplied, then all elements are updated.                        |
 +----------------------------------------------------------------------*/

FAR pdupdate(ParamBlk FAR *parm)
{
        NTI     pdnti;                  // Name table index for _PDPARMS
        Locator loc;                    // Locator to _PDPARMS
        Value   val;
        FPFI    loader;                 // Address of the loadPDParms() function
        long    checksum;               // checksum value of the address
        int     err, numelements,
                first=0, last;
        TEXT    FAR *ptr;




        pdnti = _NameTableIndex("_PDPARMS");

        if (pdnti < 0 | !_FindVar(pdnti, -1, &loc))
            _Error(644);            // Printer driver not found.

        if (loc.l_subs != 1)        // Check if _PDPARMS is an array.
            _UserError("_PDPARMS must be an array.");

        loc.l_type = 'R';           // Set up the Locator for loading the
        loc.l_where = -1;           // address of the loadPDParms() function
        loc.l_NTI = pdnti;
        loc.l_subs = 1;


/*----------------------------------------------------------------------+
 |  Note:  The address of loadPDParms() must always be in the last      |
 |  element in the _PDPARMS array.                                      |
 +----------------------------------------------------------------------*/

        numelements = loc.l_sub1 = _ALen(pdnti, AL_ELEMENTS);

        if ((err = _Load(&loc, &val)) < 0)          // Load the address element
            _Error(err);
        else

            if (val.ev_type == 'C')                 // validate the type received
            {
                _HLock(val.ev_handle);
                ptr = _HandToPtr(val.ev_handle);


                _MemMove(&loader, ptr, 4);          // Load the address
                _MemMove(&checksum, ptr+4, 4);      // Load the checksum

                _HUnLock(val.ev_handle);

                if (~ (long)loader == checksum)     // Check the address to the checksum
                {

/*----------------------------------------------------------------------+
 |  Check the types and values passed in as parameters.                 |
 +----------------------------------------------------------------------*/

                    if (parm->pCount == 0)
                        last = numelements;
                    else
                    {
                        if (parm->p[0].val.ev_long > numelements |
                                          parm->p[0].val.ev_long <= 0)
                            _Error(901);
                        else
                        {
                            first = parm->p[0].val.ev_long -1;

                            if (parm->pCount == 2)

                                if (parm->p[1].val.ev_long > numelements |
                                                parm->p[1].val.ev_long <= 0)
                                    _Error(901);
                                else
                                    last = parm->p[1].val.ev_long;
                            else
                                last = first + 1;

                            if (first > last)
                                _UserError("Invalid element range.");
                        }

                    }

/*----------------------------------------------------------------------+
 |  Make the address a FAR pointer and then call the routine.           |
 +----------------------------------------------------------------------*/

                    loader = (FPFI)MK_FP(HiWord(loader), LoWord(loader));
                    err = (*loader)(first, last);

                }
                else
                    _UserError("Invalid loadPDParms() address.");


                if (err > 0)
                    _Error(err);
            }
            else
                _UserError("loadPDParms() address must be a character type.");


}


FoxInfo myFoxInfo[] = {
    {"PDUPDATE", pdupdate, 2, ".I, .I"}
};

FoxTable _FoxTable = {
    (FoxTable FAR *)0, sizeof(myFoxInfo) / sizeof(FoxInfo), myFoxInfo
};
