|
|
/*
** Copyright(c) Microsoft Corp., 1991 *
/*
** File Name: ** ** PSPQUERY.C - PostScript Parser Handlers for Query Comments ** ** General Description: ** ** These are the routines that parse and interprete the PostScript data ** stream. This interpreter looks for PostScript Document Structuring ** Comments, which are the spooler commands that are imbedded in the ** PostScript job stream. This particular file has the code that handles ** the postscript query commands */
#include <stdio.h>
#include <string.h>
#include <search.h>
#include <windows.h>
#include <macps.h>
#include <psqfont.h>
#include <debug.h>
#include <pskey.h>
DWORD HandleFeatureLanguage(PJR pjr); DWORD HandleFeatureVersion(PJR pjr); DWORD HandleFeatureBinary(PJR pjr); DWORD HandleFeatureProduct(PJR pjr); DWORD HandleFeatureResolution(PJR pjr); DWORD HandleFeatureColor(PJR pjr); DWORD HandleFeatureVM(PJR pjr); DWORD HandleFeatureSpooler(PJR pjr); DWORD HandleBeginFeatureQuery(PJR pjr, PSZ pszQuery); DWORD HandleEndFeatureQuery(PJR pjr, PSZ pszDefaultResponse); BOOL IsFontAvailable(PQR pqr, LPSTR pszFontName); int __cdecl compare(const void * arg1, const void * arg2); LONG GetFontListResponse(PQR pqr, LPSTR pFontBuffer, DWORD cbFontBuffer, LPDWORD pcbNeeded);
/*
** HandleEndFontListQuery() ** ** Purpose: Handles the EndFontListQuery Comment ** ** Returns: Error Codes from PAPWrite Call ** */
#define DEFAULT_FONTBUF_SIZE 2048
DWORD HandleEndFontListQuery( PJR pjr ) { PQR pqr = pjr->job_pQr; LPSTR pFontBuffer = NULL; LPSTR pFontWalker = NULL; DWORD cbFontBuffer = 0; DWORD dwStatus = NO_ERROR; DWORD cbNeeded;
DBGPRINT(("Enter HandleEndFontListQuery\n"));
do { //
// allocate a typical font buffer
//
if ((pFontBuffer = (LPSTR)LocalAlloc(LPTR, DEFAULT_FONTBUF_SIZE)) == NULL) { dwStatus = GetLastError(); DBGPRINT(("ERROR: unable to allocate font buffer\n")); break; } cbFontBuffer = DEFAULT_FONTBUF_SIZE;
//
// get the fontlist response
//
if ((dwStatus = GetFontListResponse(pqr, pFontBuffer, cbFontBuffer, &cbNeeded)) != ERROR_SUCCESS) { //
// if buffer too small, reallocate and try again
//
if (dwStatus == ERROR_MORE_DATA) { LocalFree(pFontBuffer); if ((pFontBuffer = (LPSTR)LocalAlloc(LPTR, cbNeeded)) == NULL) { dwStatus = GetLastError(); DBGPRINT(("ERROR: unable to reallocate font buffer\n")); break; } cbFontBuffer = cbNeeded;
if ((dwStatus = GetFontListResponse(pqr, pFontBuffer, cbFontBuffer, &cbNeeded)) != ERROR_SUCCESS) { DBGPRINT(("ERROR: unable to get font list response\n")); break; } } }
//
// send response to client (in single font name per write)
// NOTE: While the Apple LaserWriter driver gets fonts from
// the printer in 512 byte packets that are packed with multiple
// font names, the PageMaker driver expects fonts to come in
// a single font per write scheme. So we lose the work that builds
// a font response like the Mac LaserWriter driver by sending
// the fonts as PageMaker expects them (which works for both
// drivers)
//
DBGPRINT(("writing fontlist:\n%s", pFontBuffer)); pFontWalker = pFontBuffer;
cbFontBuffer = 0;
while (*pFontWalker != '*') { cbFontBuffer = strlen(pFontWalker); if ((dwStatus = TellClient(pjr, FALSE, pFontWalker, cbFontBuffer)) != NO_ERROR) {
//
// error sending data to client
//
DBGPRINT(("ERROR: unable to send font to client\n")); break; } pFontWalker += (cbFontBuffer + 1); }
//
// do not fail if a send of a font fails. If we can get the
// termination font out, the Mac will just download any fonts
// it needs and the job will print - albeit slowly.
//
if ((dwStatus = TellClient(pjr, pjr->EOFRecvd, pFontWalker, strlen(pFontWalker))) != NO_ERROR) { DBGPRINT(("ERROR: unable to send terminating font to client\n")); break; } } while (FALSE);
if (pFontBuffer != NULL) { LocalFree (pFontBuffer); }
return dwStatus; }
//////////////////////////////////////////////////////////////////////////////
//
// GetFontListResponse - formats a fontlist buffer to send to a Mac
//
// Based on the queue type (Postscript or non), a fontlist is generated
// and placed in the supplied buffer. The font list is an ordered list
// of fonts separated by '\n\0' with a terminating font of '*\n\0'.
//
// if the buffer is too small, this routine returns ERROR_MORE_DATA.
// if for some other reason the list cannot be generated, the return
// value is ERROR_INVALID_PARAMETER.
// if the function successfully returns a font list, the return value
// is ERROR_SUCCESS.
//
//////////////////////////////////////////////////////////////////////////////
LONG GetFontListResponse( PQR pqr, LPSTR pFontBuffer, DWORD cbFontBuffer, LPDWORD pcbNeeded ) { LONG lReturn = ERROR_SUCCESS; HANDLE hFontQuery = INVALID_HANDLE_VALUE; DWORD cFonts; DWORD dwIndex; BOOL boolPSQueue; LPSTR *apszFontNames = NULL; LPSTR pTempBuffer = NULL; DWORD cbTempBuffer = cbFontBuffer; DWORD cbFontFileName; LPSTR pFont; DWORD cbFont; DWORD rc;
DBGPRINT(("enter GetFontListResponse(cbBuffer:%d, cbNeeded:%d\n", cbFontBuffer, *pcbNeeded));
do { //
// what kind of queue are we
//
if (wcscmp(pqr->pDataType, MACPS_DATATYPE_RAW)) { //
// we are PSTODIB
//
boolPSQueue = FALSE; } else { //
// we are Postscript
//
boolPSQueue = TRUE; }
//
// allocate an array of fontname pointers.
//
if (boolPSQueue) { cFonts = pqr->MaxFontIndex + 1; DBGPRINT(("cFonts=%d\n", cFonts)); apszFontNames = (LPSTR*)LocalAlloc(LPTR, cFonts * sizeof(LPSTR)); } else { //
// for PSTODIB we will need a temp buffer for the fonts as well
//
if ((pTempBuffer = (LPSTR)LocalAlloc(LPTR, cbFontBuffer)) == NULL) { lReturn = ERROR_INVALID_PARAMETER; DBGPRINT(("ERROR: unable to allocate temp font buffer\n")); break; }
if ((rc = PsBeginFontQuery(&hFontQuery)) != PS_QFONT_SUCCESS) { DBGPRINT(("ERROR: PsBeginFontQuery returns %d\n", rc)); lReturn = ERROR_INVALID_PARAMETER; break; }
if ((rc = PsGetNumFontsAvailable(hFontQuery, &cFonts)) != PS_QFONT_SUCCESS) { DBGPRINT(("ERROR: PsGetNumFontsAvailable returns %d\n", rc)); lReturn = ERROR_INVALID_PARAMETER; break; } apszFontNames = (LPSTR*)LocalAlloc(LPTR, cFonts * sizeof(LPSTR)); }
if (apszFontNames == NULL) { DBGPRINT(("ERROR: cannot allocate font list array\n")); lReturn = ERROR_INVALID_PARAMETER; break; }
//
// fill the array of fontname pointers
//
*pcbNeeded = 3; pFont = pTempBuffer; for (dwIndex = 0; dwIndex < cFonts; dwIndex++) { if (boolPSQueue) { apszFontNames[dwIndex] = pqr->fonts[dwIndex].name; *pcbNeeded += (strlen(pqr->fonts[dwIndex].name)+2); DBGPRINT(("adding font:%s, cbNeeded:%d, index:%d\n", pqr->fonts[dwIndex].name, *pcbNeeded, dwIndex)); } else { //
// pstodib - add the font to the temp buffer
// and set the pointer
//
cbFont = cbTempBuffer = cbFontBuffer; if ((rc = PsGetFontInfo(hFontQuery, dwIndex, pFont, &cbFont, NULL, &cbFontFileName)) != PS_QFONT_SUCCESS) { //
// if we are out of memory, continue enumeration
// to get size needed, but set return to ERROR_MORE_DATA
//
if (rc == PS_QFONT_ERROR_FONTNAMEBUFF_TOSMALL) { DBGPRINT(("user buffer too small for font query\n")); lReturn = ERROR_MORE_DATA; pFont = pTempBuffer; cbFont = cbTempBuffer = cbFontBuffer; if ((rc = PsGetFontInfo(hFontQuery, dwIndex, pFont, &cbFont, NULL, &cbFontFileName)) != PS_QFONT_SUCCESS) { //
// we be hosed. Fail.
//
lReturn = ERROR_INVALID_PARAMETER; DBGPRINT(("ERROR: cannot continue PSTODIB font enumeration\n")); break; } else { *pcbNeeded += cbFont + 2; } } } else { *pcbNeeded += cbFont + 2; } apszFontNames[dwIndex] = pFont; cbTempBuffer -= cbFont; pFont += cbFont; cbFont = cbTempBuffer; }
}
if (*pcbNeeded > cbFontBuffer) { lReturn = ERROR_MORE_DATA; break; }
//
// build the fontlistresponse
//
cbFontBuffer = 0; for (dwIndex = 0; dwIndex < cFonts; dwIndex++) { cbFont = sprintf(pFontBuffer, "%s\n", apszFontNames[dwIndex]) + 1; pFontBuffer += cbFont; cbFontBuffer += cbFont; }
memcpy (pFontBuffer, "*\n", 3); } while (FALSE);
if (apszFontNames != NULL) { LocalFree(apszFontNames); }
if (pTempBuffer != NULL) { LocalFree(pTempBuffer); }
if (hFontQuery != INVALID_HANDLE_VALUE) { PsEndFontQuery(hFontQuery); }
return (lReturn); }
int __cdecl compare(const void* arg1, const void* arg2) { return _stricmp(* (char **)arg1, * (char **)arg2); }
//
// For Postscript printers, the font enumeration technique is complex.
// EnumFontFamilies expects the programmer to specify a callback function
// that will be called either once for every font family, or once for
// every font face in a family. To get all fonts available, I use
// EnumFontFamilies twice. The first enumeration, I call EnumFontFamilies
// with a null value for the family name. This causes the callback
// function to be called once for each family name installed. This
// callback function then does an enumeration on that family name to
// get the specific face names in the family. This second layer of
// enumeration specifies yet another callback function that returns
// the font name to the Macintosh client.
//
void EnumeratePostScriptFonts( PJR pjr ) { PQR pqr = pjr->job_pQr;
DBGPRINT(("ENTER EnumeratePostScriptFonts\n"));
if (pjr->hicFontFamily != NULL) { //
// enumerate the font families
//
EnumFontFamilies(pjr->hicFontFamily, NULL, (FONTENUMPROC)FamilyEnumCallback, (LPARAM)pjr); } }
int CALLBACK FamilyEnumCallback( LPENUMLOGFONT lpelf, LPNEWTEXTMETRIC pntm, int iFontType, LPARAM lParam ) { PQR pqr = ((PJR)lParam)->job_pQr; PJR pjr = (PJR)lParam;
DBGPRINT(("Enter FamilyEnumCallback for family %ws\n", lpelf->elfFullName));
//
// enumerate the fonts in this family
//
if (iFontType & DEVICE_FONTTYPE) { DBGPRINT(("enumerating face names\n")); EnumFontFamilies(pjr->hicFontFace, lpelf->elfFullName, (FONTENUMPROC)FontEnumCallback, lParam); } else { DBGPRINT(("this family is not a DEVICE_FONTTYPE\n")); }
return 1; }
int CALLBACK FontEnumCallback( LPENUMLOGFONT lpelf, LPNEWTEXTMETRIC pntm, int iFontType, LPARAM lParam ) { DWORD PAPStatus; PJR pjr = (PJR)lParam; BYTE pszFontName[255];
DBGPRINT(("Enter FontEnumCallback\n"));
//
// return this font name to the client
//
if (iFontType & DEVICE_FONTTYPE) { CharToOem(lpelf->elfFullName, pszFontName); if (PAPStatus = TellClient(pjr, FALSE, pszFontName, strlen(pszFontName))) { DBGPRINT(("ERROR: TellClient returns %d\n", PAPStatus)); } } else { DBGPRINT(("%ws is not a DEVICE_FONTTYPE\n", lpelf->elfFullName)); }
return 1; }
/*
** HandleEndQuery() ** ** Purpose: PageMaker will send a query that goes like this: ** ** %%BeginQuery ** ... ** %%EndQuery (spooler) ** ** In order to allow pagemaker to print TIFF formated images ** properly, we should respond to this query with "printer". ** ** Returns: Error Codes from PAPWrite Call ** */ DWORD HandleEndQuery( PJR pjr, PBYTE ps ) { char *token; CHAR pszResponse[PSLEN+1];
DBGPRINT(("Enter HandleEndQuery\n")); token = strtok(NULL,"\n");
if (token == NULL) { return NO_ERROR; }
/* strip off any leading blanks in the default */ token += strspn(token, " ");
//
// respond with the default
//
sprintf(pszResponse, "%s\x0a", token); return (TellClient(pjr, pjr->EOFRecvd, pszResponse, strlen(pszResponse))); }
/***************************************************************************
** FinishDefaultQuery() ** ** Purpose: Scans for the PostScript command specified in psKeyWord. It ** then will respond with the default response specified on that ** line. It will set the InProgress field in the JOB_RECORD to ** an InProgress value if the default is not found in this buffer. ** ** Returns: Error Codes from PAPWrite Call ** ***************************************************************************/ DWORD FinishDefaultQuery( PJR pjr, PBYTE ps ) { char * token; char buf[PSLEN+1];
DBGPRINT(("FinishDefaultQuery: %s\n", ps));
if (NULL == (token = strtok (ps," :"))) { return (NO_ERROR); }
pjr->InProgress= NOTHING;
/* First We Should Handle the cases that do not use the default response */
if (!_stricmp(token, EFEATUREQUERY)) return (HandleEndFeatureQuery(pjr, strtok (NULL," \n")));
if (!_stricmp(token, EFONTLISTQ)) return( HandleEndFontListQuery (pjr));
if (!_stricmp(token, EQUERY)) return( HandleEndQuery (pjr, ps));
if (!_stricmp(token, EPRINTERQUERY)) return( HandleEndPrinterQuery(pjr));
if (!_stricmp(token, EVMSTATUS)) { sprintf(buf, "%ld", pjr->job_pQr->FreeVM); return (TellClient(pjr, pjr->EOFRecvd, buf , strlen(buf))); }
if ((token = strtok(NULL,"\n")) == NULL) { return (NO_ERROR); }
/* strip off any leading blanks in the default. Append a LF */ token += strspn(token, " "); sprintf(buf, "%s\x0a", token); return (TellClient(pjr, pjr->EOFRecvd, buf, strlen(buf))); }
DWORD HandleEndFeatureQuery( PJR pjr, PSZ pszDefaultResponse) {
DWORD rc = NO_ERROR; CHAR pszResponse[PSLEN];
DBGPRINT(("enter HandleEndFeatureQuery\n"));
do { //
// return the default response if there is one
//
if (NULL != pszDefaultResponse) { sprintf(pszResponse, "%s\x0a", pszDefaultResponse); DBGPRINT(("responding with default response from query: %s\n", pszResponse)); rc = TellClient(pjr, pjr->EOFRecvd, pszResponse, strlen(pszResponse)); break; }
DBGPRINT(("responding with Unknown\n")); rc = TellClient(pjr, pjr->EOFRecvd, DEFAULTRESPONSE, strlen(DEFAULTRESPONSE));
} while (FALSE);
return rc; }
/*
** Routine: ** ParseDict ** ** Purpse: ** ** This routine will take a given QueryProcSet, BeginProcSet, or ** IncludeProcSet comment and determine what dictionary is being ** referenced. ** ** Entry: ** ** Address of a record to fill in with the Dictionary information. ** ** Exit: ** ** Filed in structure ** */ void FindDictVer( PDR pdr ) { char *token;
pdr->name[0] = 0; pdr->version[0] = 0; pdr->revision[0] = 0;
DBGPRINT(("Enter FindDictVer\n"));
/* lets look for a line like this: "(appledict md)" 67 0 */ token = strtok(NULL,"() \""); /* this should be appledict */
if (token !=NULL) { /*/
** If the token is "Appledict", then we need to parse again to get ** the real dict name. */ if (!_stricmp(token, APPLEDICTNAME)) token = strtok(NULL,"() \""); /* this sholud be md, or some other dict name */
if (token != NULL) { strcpy(pdr->name, token); token = strtok(NULL," \"");
if (token != NULL) { strcpy(pdr->version,token); token = strtok(NULL," \"");
if (token != NULL) strcpy(pdr->revision,token); } } } DBGPRINT(("FindDictVer: %s:%s:%s\n", pdr->name, pdr->version, pdr->revision)); } // End of FindDictVer
struct commtable { PSZ commentstr; DWORD (*pfnHandle)(PJR, PSZ); PSZ parmstr; } qrytable [] = { { BPROCSETQUERY, HandleBeginProcSetQuery, NULL }, { BFONTQUERY, HandleBeginFontQuery, NULL }, { NULL, NULL, NULL } };
/*
** ** HandleBQCommentEvent() ** ** Purpose: Handles Begin Query Comment Events. ** ** Returns: Error Codes */ DWORD HandleBQComment( PJR pjr, PBYTE ps ) { PSZ token; PSZ qrytoken; PSZ endquery = EQCOMMENT; DWORD status = NO_ERROR; struct commtable *pct;
DBGPRINT(("Enter HandleBQComment\n"));
//
// Parse the keyword
//
if ((token= strtok(ps," :")) != NULL) { DBGPRINT(("query: %s\n", token));
// found the keyword, call the correct handler
for (pct = qrytable; pct->pfnHandle != NULL; pct++) { if (!strcmp(token, pct->commentstr)) { status = pct->pfnHandle(pjr, pct->parmstr == NULL ? ps : pct->parmstr); if (status == (DWORD)-1) // Special error code, handle it the default way
{ status = NO_ERROR; break; } return (status); } }
// special case the BeginFeatureQuery comment as the item
// being queried comes as the next token
if (!strcmp(token, BFEATUREQUERY)) { status = HandleBeginFeatureQuery(pjr, strtok(NULL," \n\x09")); return (status); }
// special case the BeginQuery comment for the same reasons
// as BeginFeatureQuery
if (!strcmp(token, BQUERY)) { qrytoken = strtok(NULL, " \n\x09"); if (NULL != qrytoken) { status = HandleBeginFeatureQuery(pjr, qrytoken); return (status); } }
// keyword not recognized, parse as unknown comment. Token is
// of form %%?BeginXXXXQuery. Change this to the form %%?EndXXXXQuery
// and pass it to HandleBeginXQuery.
token += sizeof(BQCOMMENT) - sizeof(EQCOMMENT); strncpy(token, EQCOMMENT, sizeof(EQCOMMENT)-1); HandleBeginXQuery(pjr, token); }
return (status); }
struct featurecommtable { PSZ commentstr; DWORD (*pfnHandle)(PJR); } featureqrytable [] = { { FQLANGUAGELEVEL, HandleFeatureLanguage }, { FQPSVERSION, HandleFeatureVersion }, { FQBINARYOK, HandleFeatureBinary }, { FQPRODUCT, HandleFeatureProduct }, { FQPRODUCT1, HandleFeatureProduct }, { FQRESOLUTION, HandleFeatureResolution }, { FQCOLORDEVICE, HandleFeatureColor }, { FQFREEVM, HandleFeatureVM }, { FQTOTALVM, HandleFeatureVM }, { FQSPOOLER, HandleFeatureSpooler }, { NULL, NULL } };
DWORD HandleBeginFeatureQuery( PJR pjr, PSZ pszQuery ) { DWORD i, rc = NO_ERROR; struct featurecommtable *pct;
DBGPRINT(("enter HandleBeginFeatureQuery:%s\n", pszQuery));
do { //
// if we have no query keyword, break;
//
if (NULL == pszQuery) { DBGPRINT(("NULL feature\n")); break; }
// Strip out any trailing CR/LF before comparing
for (i = strlen(pszQuery) - 1; ; i--) { if ((pszQuery[i] != CR) && (pszQuery[i] != LINEFEED)) break; pszQuery[i] = 0; } //
// walk the list of known feature queries and call the appropriate
// feature query handler
//
for (pct = featureqrytable; pct->pfnHandle != NULL; pct++) { if (!strcmp(pszQuery, pct->commentstr)) { rc = pct->pfnHandle(pjr); break; } }
if (NULL == pct->pfnHandle) { DBGPRINT(("WARNING: feature query not found\n")); pjr->InProgress = QUERYDEFAULT; }
} while (FALSE);
return rc; }
DWORD HandleFeatureLanguage( PJR pjr ) { CHAR pszResponse[PSLEN]; //
// this routine should respond with the PostScript language level
// supported by the printer. The response is in the form "<level>"
// where <level> is PostScript language level - either a 1 or a 2 at
// the time of this writing.
//
DBGPRINT(("enter HandleFeatureLanguage\n"));
sprintf(pszResponse, "\"%s\"\x0a", pjr->job_pQr->pszLanguageLevel); DBGPRINT(("responding with:%s\n", pszResponse)); return (TellClient(pjr, pjr->EOFRecvd, pszResponse, strlen(pszResponse))); }
DWORD HandleFeatureVersion( PJR pjr ) { CHAR pszResponse[PSLEN];
DBGPRINT(("enter HandleFeatureVersion\n"));
sprintf(pszResponse, "\"(%s) %s\"\x0a", pjr->job_pQr->Version, pjr->job_pQr->Revision); DBGPRINT(("responding with:%s\n", pszResponse)); return (TellClient(pjr, pjr->EOFRecvd, pszResponse, strlen(pszResponse))); }
DWORD HandleFeatureBinary( PJR pjr ) { DBGPRINT(("enter HandleFeatureBinary\n"));
return (TellClient(pjr, pjr->EOFRecvd, pjr->job_pQr->SupportsBinary ? "True\x0a" : "False\x0a", pjr->job_pQr->SupportsBinary ? 5: 6)); }
DWORD HandleFeatureProduct( PJR pjr ) { CHAR pszResponse[PSLEN];
DBGPRINT(("enter HandleFeatureProduct\n"));
sprintf(pszResponse, "\"(%s)\"\x0a", pjr->job_pQr->Product); DBGPRINT(("responding with:%s\n", pszResponse)); return (TellClient(pjr, pjr->EOFRecvd, pszResponse, strlen(pszResponse)));
}
DWORD HandleFeatureResolution( PJR pjr ) { CHAR pszResponse[PSLEN];
DBGPRINT(("enter HandleFeatureResolution\n"));
sprintf(pszResponse, "%s\x0a", pjr->job_pQr->pszResolution); DBGPRINT(("responding with:%s\n", pszResponse)); return (TellClient(pjr, pjr->EOFRecvd, pszResponse, strlen(pszResponse))); }
DWORD HandleFeatureColor (PJR pjr) { CHAR pszResponse[PSLEN];
DBGPRINT(("enter HandleFeatureColor\n"));
sprintf(pszResponse, "%s\x0a", pjr->job_pQr->pszColorDevice); DBGPRINT(("responding with:%s\n", pszResponse)); return (TellClient(pjr, pjr->EOFRecvd, pszResponse, strlen(pszResponse))); }
DWORD HandleFeatureVM( PJR pjr ) { CHAR pszResponse[PSLEN];
DBGPRINT(("enter HandleFeatureVM\n"));
sprintf(pszResponse, "\"%d\"\x0a", pjr->job_pQr->FreeVM); DBGPRINT(("responding with:%s\n", pszResponse)); return (TellClient(pjr, pjr->EOFRecvd, pszResponse, strlen(pszResponse))); }
DWORD HandleFeatureSpooler( PJR pjr ) { DBGPRINT(("enter HandleFeatureSpooler\n")); return (TellClient(pjr, pjr->EOFRecvd, "1 \x0a", 3)); }
/*
** HandleBeginProcSetQuery() ** ** Purpose: Handles BeginProcSetQuery Comment Events. ** ** Returns: Number of lines that should be skipped before scanning ** for another event starts again. */ DWORD HandleBeginProcSetQuery( PJR pjr, PSZ dummy ) { DICT_RECORD QDict; PQR pqr = pjr->job_pQr; DWORD rc;
DBGPRINT(("Enter HandleBeginProcSetQuery\n"));
//
// the dictionary the job is looking for determines what
// client version the job originated from.
//
FindDictVer(&QDict);
//
// if we are a 5.2 client, then reset this to be a PSTODIB job
//
if ((_stricmp(QDict.name, MDNAME) == 0) && (_stricmp(QDict.version, CHOOSER_52) == 0)) { DBGPRINT(("a 5.2 client - we do not support him\n")); rc = ERROR_NOT_SUPPORTED; } else { // we don't cache any other dictionaries, so tell client we
// don't have it
rc = TellClient(pjr, pjr->EOFRecvd, PROCSETMISSINGRESPONSE, strlen(PROCSETMISSINGRESPONSE)); }
return rc; }
/*
** ** HandleBeginFontQuery() ** ** Purpose: Handles BeginFontQuery Comment Events. ** ** Returns: PAPWrite Error Codes ** */ DWORD HandleBeginFontQuery( PJR pjr, PSZ ps ) { PQR pqr = pjr->job_pQr; CHAR response[PSLEN + 3]; LPSTR pszResponseFont = response; DWORD cbResponseUsed = 0; LPSTR requestedFont = NULL; DWORD len= 0; DWORD rc = NO_ERROR;
DBGPRINT(("Enter HandleBeginFontQuery\n"));
do { // parse out the fontname list
requestedFont= strtok(NULL,"\n");
if (NULL == requestedFont) { rc = (DWORD)-1; // Special error code to indicate we want default handling
break; }
len = strlen(requestedFont);
DBGPRINT(("requesting font list:%s. Length: %d\n", requestedFont, len));
// Mac will request status on a list of fonts separated by spaces.
// for each font we respond with /fontname:yes or /fontname:no and
// bundle this response into one write
requestedFont = strtok(requestedFont, " "); while (requestedFont != NULL) { DBGPRINT(("looking for font:%s\n", requestedFont));
// enough space for response?
if (PSLEN < (cbResponseUsed + strlen(requestedFont) + sizeof(":yes "))) { DBGPRINT(("out of space for response\n")); break; }
if (IsFontAvailable(pqr, requestedFont)) { sprintf(pszResponseFont, "/%s:Yes\x0a", requestedFont); } else { sprintf(pszResponseFont, "/%s:No\x0a", requestedFont); }
cbResponseUsed += strlen(pszResponseFont); pszResponseFont += strlen(pszResponseFont); requestedFont = strtok(NULL, " "); } } while (FALSE);
strcpy (pszResponseFont, "*\x0a");
if (NO_ERROR == rc) { DBGPRINT(("responding with:%s", response)); rc = TellClient(pjr, pjr->EOFRecvd, response, strlen(response)); }
return rc; }
BOOL IsFontAvailable( PQR pqr, LPSTR pszFontName ) { BOOL rc = FALSE; DWORD i; PFR fontPtr; HANDLE hFontQuery = INVALID_HANDLE_VALUE; DWORD cFonts; DWORD dummy; CHAR pszFont[PPDLEN + 1]; DWORD cbFont = 0; DWORD err;
DBGPRINT(("enter IsFontAvailable\n"));
do { //
// fonts for Postscript queues different than for PSTODIB queues
//
if (!wcscmp(pqr->pDataType, MACPS_DATATYPE_RAW)) { //
// do a PostScript queue font search
//
DBGPRINT(("starting font search on PostScript queue\n"));
for (i = 0, fontPtr = pqr->fonts; i <= pqr->MaxFontIndex; i++, fontPtr++) { if (!_stricmp(pszFontName, fontPtr->name)) { DBGPRINT(("found the font\n")); rc = TRUE; break; } } } else { //
// do a PSTODIB font search
//
DBGPRINT(("starting font search on PSTODIB queue\n"));
if (PS_QFONT_SUCCESS != (PsBeginFontQuery(&hFontQuery))) { DBGPRINT(("PsBeginFontQuery fails\n")); hFontQuery = INVALID_HANDLE_VALUE; break; }
if (PS_QFONT_SUCCESS != (PsGetNumFontsAvailable(hFontQuery, &cFonts))) { DBGPRINT(("psGetNumFontsAvailable fails\n")); break; }
for (i = 0; i < cFonts; i++) { cbFont = PPDLEN + 1; dummy = 0; err = PsGetFontInfo(hFontQuery, i, pszFont, &cbFont, NULL, &dummy); if (PS_QFONT_SUCCESS != err) { DBGPRINT(("PsGetFontInfo fails with %d\n", err)); break; }
if (0 == _stricmp(pszFontName, pszFont)) { DBGPRINT(("found the font\n")); rc = TRUE; break; } } } } while (FALSE);
if (INVALID_HANDLE_VALUE != hFontQuery) { PsEndFontQuery(hFontQuery); }
return rc; }
/*
** ** HandleEndPrinterQuery() ** ** Purpose: Handles EndPrinterQuery Comment Events. ** */ DWORD HandleEndPrinterQuery( PJR pjr ) { char reply[PSLEN+1]; PQR QPtr = pjr->job_pQr;
DBGPRINT(("Enter HandleEndPrinterQuery\n"));
/* respond with revision number, version and product */ sprintf(reply, "%s\n(%s)\n(%s)\n", QPtr->Revision, QPtr->Version, QPtr->Product);
/* respond to the client */ return (TellClient(pjr, pjr->EOFRecvd, reply, strlen(reply))); }
/*
** HandleBeginXQuery() ** ** Purpose: Handles BeginQuery Comment Events. */ void HandleBeginXQuery( PJR pjr, PSZ string ) { DBGPRINT(("BeginQuery: %s\n", string)); strcpy(pjr->JSKeyWord, string); pjr->InProgress=QUERYDEFAULT; }
|