📄 driver2.c
字号:
/*----------------------------------------------------------------------+
| DRIVER2.C - FoxPro general printer driver (C version). |
| |
| Copyright (c) 1991, Fox Holdings, Inc. |
| Fox Software System's Group |
| 134 W. South Boundary |
| Perrysburg, Ohio 43551 |
+----------------------------------------------------------------------*/
#include <pro_ext.h>
#define BADHANDLE 0 // Not a handle.
typedef unsigned short USHORT;
#define LoWord(x) ((USHORT)x)
#define HiWord(x) ((USHORT)((unsigned long)(x)>>16))
#define P_BOLD 1 // Bold attrib.
#define P_ITALIC (1<<1) // Italic attrib.
#define P_UNDERLINE (1<<2) // Underline attrib.
#define P_RAISED (1<<3) // Superscript attrib.
#define P_LOWERED (1<<4) // Subscript. attrib.
#define NUMWIDTH 20
#define PDALLOCSIZE 1024 // Allocation size
#define PDELEMENTS 52 // Number of elements in _PDPARMS
#define CAPTUREBUFFSIZE 64
#define TIMESLOADED 43 // Array position of the number times we're loaded
static Locator g_pdparms; // The locator of _PDPARMS
static MHANDLE g_pdElement[PDELEMENTS]; // Our local copy of _PDPARMS
static int g_pdELen[PDELEMENTS]; // Length of individual elements
static long g_docwidth, g_curlin; // Document width, current line #
static TEXT g_sendff = FALSE; // Flag for sending a Form Feed
static TEXT g_bop = FALSE; // Beginning of a page
static MHANDLE g_capture; // capture buffer
static int g_caplen; // capture buffer length
static double g_dots_col=0; // dots per column
static int g_curcolumn=0; // current column location
static int g_graph_width=0; // width of a graphic character
static TEXT g_viadots=FALSE; // flag to show if we move by dots
// or by columns.
/*----------------------------------------------------------------------+
| _fltused() is a null function so that WATCOM does not link in |
| unneeded code into our library. If there is ever a need to add |
| floating point functions like sprintf() and vsprintf() this routine |
| should be removed. |
+----------------------------------------------------------------------*/
void _fltused()
{
}
/*----------------------------------------------------------------------+
| power() will return the base parameter raised to the nth. |
+----------------------------------------------------------------------*/
static long power(int base, int n)
{
long res=base;
if (n < 1)
return 1;
while (--n)
res *= base;
return res;
}
/*----------------------------------------------------------------------+
| This routine will do the xBase equivalent of a LTRIM() and return |
| the length of the trimmed string. |
+----------------------------------------------------------------------*/
static long LeftTrim(Value FAR *val)
{
TEXT FAR *buff;
int i;
_HLock(val->ev_handle);
buff = _HandToPtr(val->ev_handle);
for (i=0; i <= val->ev_length && buff[i] == 0x20; i++);
_MemMove(buff, buff+i, val->ev_length - i);
_HUnLock(val->ev_handle);
_SetHandSize(val->ev_handle, val->ev_length - i);
val->ev_length -= i;
return (val->ev_length);
}
/*----------------------------------------------------------------------+
| This routine takes a long integer and returns the string equivalent |
| of it. |
+----------------------------------------------------------------------*/
static NumToStr(long num, TEXT FAR *result)
{
TEXT buff[10], *firstch;
long temp;
buff[9] = 0;
firstch = buff+9;
do
{
temp = num / 10;
*--firstch = (num - temp * 10) + '0'; // convert the nibble to ASCII
num = temp;
}
while (num && (firstch > buff));
_StrCpy(result, firstch); // copy the string into result.
return _StrLen(result);
}
/*----------------------------------------------------------------------+
| RealNumToStr() will convert the double real number to a character |
| string and return it in result. |
+----------------------------------------------------------------------*/
static int RealNumToStr(double d, TEXT FAR *result, int decpl)
{
TEXT buff[NUMWIDTH * 2];
long lval;
int reslen, i;
lval = d * power(10, decpl) + 0.5001;
NumToStr(lval, buff);
reslen = _StrLen(buff);
if (reslen <= decpl)
{
_StrCpy(result, "0.");
i = decpl - reslen;
_MemFill(result + 2, '0', i);
_StrCpy(result + 2 + i, buff);
}
else
{
i = reslen - decpl;
_MemMove(result, buff, i);
if (decpl)
{
result[i] = '.';
_MemMove(result + i + 1, buff + i, decpl);
i += (decpl + 1);
}
result[i] = 0;
}
return _StrLen(result);
}
/*----------------------------------------------------------------------+
| StrToNum will convert the string passed in cp into a number. |
+----------------------------------------------------------------------*/
static double StrToNum(TEXT FAR *cp, int numlen)
{
double resnum = 0.0;
int j;
for(; *cp == ' '; cp++, numlen--);
for (; isdigit(*cp) && numlen; cp++, numlen--)
resnum = (resnum * 10) + (*cp - '0');
if ((*cp == '.') && numlen--)
{
cp++;
for (j=10 ; isdigit(*cp) && numlen; cp++, numlen--, j *= 10)
resnum += ((*cp - '0') / j);
}
return resnum;
}
/*----------------------------------------------------------------------+
| Retrieve all values from _pdparms directly (except for 'C' type). |
+----------------------------------------------------------------------*/
static pdVal(int element, TEXT type, Value FAR *val)
{
Locator loc;
loc = g_pdparms; // The locator of _PDPARMS.
loc.l_sub1 = element;
if (_Load(&loc, val) != 0) // Load the element
return NO;
if (val->ev_type != type) // Check if it's the type we want
{
if ((val->ev_type == 'C') && (val->ev_handle != BADHANDLE))
{
_FreeHand(val->ev_handle); // If it's a Character type, then
val->ev_handle = BADHANDLE; // free the handle.
}
return NO;
}
return YES;
}
/*----------------------------------------------------------------------+
| Retrieve the numeric values from _PDPARMS |
+----------------------------------------------------------------------*/
static double pdNval(int element)
{
Value val;
double retval;
if (pdVal(element, 'N', &val) || pdVal(element, 'I', &val))
{
retval = (val.ev_type == 'N') ? val.ev_real : val.ev_long;
return (retval);
}
return (double)0.0;
}
/*----------------------------------------------------------------------+
| Retrieve the character values from _PDPARMS |
+----------------------------------------------------------------------*/
static pdCval(int element, TEXT FAR *dest, int FAR *destlen)
{
int len;
--element; // decrement element for our copy
len = g_pdELen[element]; // get the length of the element
if (len == 0) // if the length is zero, it isn't good
return;
// move the element into the destination
_MemMove(dest + *destlen,
_HandToPtr(g_pdElement[element]),
len);
*destlen += len;
}
/*----------------------------------------------------------------------+
| Store a numeric value in _PDPARMS |
+----------------------------------------------------------------------*/
static void pdStoreNVal(int element, long nval)
{
Locator loc;
Value val;
val.ev_type = 'I'; // Setup the Value Structure for the _Store
val.ev_width = 10;
val.ev_long = nval;
val.ev_handle = BADHANDLE;
loc = g_pdparms; // Specify what element we want to use
loc.l_sub1 = element;
_Store(&loc, &val); // Store the value into _PDPARMS.
}
/*----------------------------------------------------------------------+
| Store a numeric real value in _PDPARMS |
+----------------------------------------------------------------------*/
static void pdStoreRVal(int element, double nval)
{
Locator loc;
Value val;
val.ev_type = 'N'; // Setup the Value Structure for the _Store
val.ev_width = 10;
val.ev_real = nval;
val.ev_length = 2;
val.ev_handle = BADHANDLE;
loc = g_pdparms; // Specify what element we want to use
loc.l_sub1 = element;
_Store(&loc, &val); // Store the value into _PDPARMS.
}
static loadPDParms(int start, int end)
{
int element; // the element we are addressing
int errcode=0; // internal error code
Locator loc; // a locator to _PDPARMS
Value val; // the value structure for _PDPARMS
/* Load in the values of each element of _PDPARMS in our local
copy. */
for (element=start; (element < end) && (element < PDELEMENTS); element++)
{
loc = g_pdparms;
loc.l_sub1 = element+1; // Increment the element # for xBase
if (errcode = _Load(&loc, &val)) // Load the value
break;
// Check the type of the element is not character or we don't have a handle
if ((val.ev_type != 'C') || (val.ev_handle == BADHANDLE))
{
g_pdElement[element] = BADHANDLE;
g_pdELen[element] = 0;
}
else // otherwise, it's a character type
{
g_pdElement[element] = val.ev_handle; // save the handle and
g_pdELen[element] = val.ev_length; // and the length
}
}
return (-errcode); // Set a flag if there was an error
}
/*----------------------------------------------------------------------+
| This routine is called on loading of the api printer driver. It |
| checks to see if _PDPARMS has been created and if so, it then loads |
| in the values of the elements of the array into an internal copy. |
| This is done once, so any changes made to the xBase version of |
| _PDPARMS after this, will not take any effect on our copy. This is |
| done so we don't continually have to call back to FoxPro to obtain |
| the value of a certain element in _PDPARMS array. |
+----------------------------------------------------------------------*/
FAR pdonload()
{
Locator loc; // a locator to _PDPARMS
int errcode; // internal error code
NTI nti; // the Name Table Index of _PDPARMS
Value val; // the value structure for _PDPARMS
int element; // the element we are addressing
TEXT varflag = FALSE,
create = FALSE;
FPFI load_func;
TEXT load_elem[20];
int load_len=0;
long chksum;
// check if there is a Name Table Index
if ((nti = _NameTableIndex("_PDPARMS")) >= 0)
{
if (_FindVar(nti, -1, &loc)) // Load the Locator for _PDPARMS
{
if (loc.l_subs == 0) // If there aren't any subscripts,
varflag = TRUE; // flag that there is an error with it
else
{
g_pdparms = loc;
varflag = loadPDParms(0, loc.l_sub1);
/*----------------------------------------------------------------------+
| The following line tells us how many times this api routine has been|
| loaded. This is needed in case a user loads a printer drivers and |
| thus the api, and then loads the api routine via the SET LIBRARY TO |
| command. Without this, we would release the local copy of _PDPARMS |
| (which rely heavily upon.) |
+----------------------------------------------------------------------*/
if (loc.l_subs >= TIMESLOADED)
pdStoreNVal(TIMESLOADED, pdNval(TIMESLOADED) + 1);
else
varflag = TRUE;
/*----------------------------------------------------------------------+
| The following code was added as and enhancement request. It stores |
| the address of the procedure loadPDParms and a four byte checksum |
| of this address into the last element of _PDPARMS. If the user |
| wants to update the api's internal copy of _PDPARMS, it can now |
| be done by loading the library PDUDATE.PLB. |
| |
| Note: The address of loadPDParms() function must be placed in the |
| last element in the _PDPARMS array in order for PDUPDATE to work. |
+----------------------------------------------------------------------*/
load_func = loadPDParms;
_MemMove(load_elem, &load_func, 4);
load_len = 4;
chksum = ~(long) load_func;
_MemMove(load_elem + load_len, &chksum, 4);
load_len +=4;
val.ev_type = 'C';
val.ev_handle = _AllocHand(load_len);
if (val.ev_handle != BADHANDLE)
{
val.ev_length = load_len;
_MemMove(_HandToPtr(val.ev_handle), load_elem, load_len);
}
else
val.ev_length = 0;
if ((loc.l_sub1 = _ALen(nti, AL_ELEMENTS)) >= 0)
_Store(&loc, &val);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -