Annotation of ntddk/src/print/pslib/ppd.c, revision 1.1.1.1

1.1       root        1: //--------------------------------------------------------------------------
                      2: //
                      3: // Module Name:  PPD.C
                      4: //
                      5: // Brief Description:  This module contains the PSCRIPT driver's PPD
                      6: // Compiler.
                      7: //
                      8: // Author:  Kent Settle (kentse)
                      9: // Created: 20-Mar-1991
                     10: //
                     11: // Copyright (c) 1991 Microsoft Corporation
                     12: //
                     13: // This module contains routines which will take an Adobe PPD (printer
                     14: //--------------------------------------------------------------------------
                     15: 
                     16: #include "string.h"
                     17: #include "pscript.h"
                     18: 
                     19: #define TESTING 0
                     20: #define SIZE_TEST 0
                     21: 
                     22: #define MAX_PS_NAME     256
                     23: 
                     24: // declarations of routines residing within this module.
                     25: 
                     26: VOID InitNTPD(PNTPD);
                     27: int GetString(char *, PPARSEDATA);
                     28: void GetDimension(PAPERDIM *, PPARSEDATA);
                     29: void GetImageableArea(RECTL *, PPARSEDATA);
                     30: int szLength(char *);
                     31: VOID BuildNTPD(PNTPD, PTMP_NTPD);
                     32: DWORD SizeNTPD(PNTPD, PTMP_NTPD);
                     33: int GetKeyword(TABLE_ENTRY *, PPARSEDATA);
                     34: VOID GetOptionString(PSTR, DWORD, PPARSEDATA);
                     35: int GetOptionIndex(TABLE_ENTRY *, PPARSEDATA);
                     36: int MapToken(char *, TABLE_ENTRY *);
                     37: VOID GetWord(char *, int, PPARSEDATA);
                     38: VOID ParsePPD(PNTPD, PTMP_NTPD, PPARSEDATA);
                     39: BOOL GetLine(PPARSEDATA);
                     40: VOID UnGetLine(PPARSEDATA);
                     41: VOID EatWhite(PPARSEDATA);
                     42: BOOL szIsEqual(char *, char *);
                     43: BOOL GetBuffer(PPARSEDATA);
                     44: int GetNumber(PPARSEDATA);
                     45: int GetFloat(int, PPARSEDATA);
                     46: int NameComp(CHAR *, CHAR *);
                     47: VOID ParseProtocols(PPARSEDATA, PNTPD);
                     48: 
                     49: // external declarations.
                     50: 
                     51: extern TABLE_ENTRY KeywordTable[];
                     52: extern TABLE_ENTRY SecondKeyTable[];
                     53: extern TABLE_ENTRY FontTable[];
                     54: 
                     55: //--------------------------------------------------------------------------
                     56: //
                     57: // VOID InitNTPD(pntpd);
                     58: // PNTPD    pntpd;
                     59: //
                     60: // Fills in the NTPD structure with initial values.
                     61: //
                     62: // Returns:
                     63: //   This routine returns no value.
                     64: //
                     65: // History:
                     66: //   22-Mar-1991    -by-    Kent Settle    (kentse)
                     67: //  Wrote it.
                     68: //--------------------------------------------------------------------------
                     69: 
                     70: VOID InitNTPD(pntpd)
                     71: PNTPD   pntpd;
                     72: {
                     73:     pntpd->cjThis = sizeof(NTPD);
                     74:     pntpd->flFlags = 0;
                     75:     pntpd->ulVersion = (ULONG)NTPD_VERSION;
                     76:     pntpd->iDefResolution = DEF_RESOLUTION;
                     77:     pntpd->LangLevel = 1;
                     78: }
                     79: 
                     80: 
                     81: //--------------------------------------------------------------------------
                     82: //
                     83: // VOID ParsePPD(pntpd, ptmp, pdata);
                     84: // PNTPD        pntpd;
                     85: // PTMP_NTPD    ptmp;
                     86: // PPARSEDATA   pdata;
                     87: //
                     88: // Parses the PPD file, building the TMP_NTPD structure as it goes.
                     89: //
                     90: // Returns:
                     91: //   This routine returns no value.
                     92: //
                     93: // History:
                     94: //   03-Apr-1991    -by-    Kent Settle    (kentse)
                     95: //  Wrote it.
                     96: //--------------------------------------------------------------------------
                     97: 
                     98: VOID ParsePPD(pntpd, ptmp, pdata)
                     99: PNTPD       pntpd;
                    100: PTMP_NTPD   ptmp;
                    101: PPARSEDATA  pdata;
                    102: {
                    103:     int     iKeyword;
                    104:     int     i, j;
                    105:     char    szWord[256];
                    106: 
                    107:     while (TRUE)
                    108:     {
                    109:         // get the next line from the PPD file.
                    110: 
                    111:         if (GetLine(pdata))
                    112:         {
                    113: #if TESTING
                    114:             DbgPrint("Normal End of File.\n");
                    115: #endif
                    116:             break;
                    117:         }
                    118: 
                    119:         // get the next Keyword from the PPD file.
                    120: 
                    121:         iKeyword = GetKeyword(KeywordTable, pdata);
                    122: 
                    123:         // we are done if end of file.
                    124: 
                    125:         if (iKeyword == TK_EOF)
                    126:             break;
                    127: 
                    128:         // there will actually be a lot of Keywords we don't care
                    129:         // about.  for speed's sake, let's trap them here.
                    130: 
                    131:         if (iKeyword == TK_UNDEFINED)
                    132:             continue;
                    133: 
                    134:         switch (iKeyword)
                    135:         {
                    136:             case COLORDEVICE:
                    137:                 GetWord(szWord, sizeof(szWord), pdata);
                    138:                if (!(strncmp(szWord, "True", 4)))
                    139:                 {
                    140:                     pntpd->flFlags |= COLOR_DEVICE;
                    141: #if TESTING
                    142:                    DbgPrint("Device is Color.\n");
                    143: #endif
                    144:                 }
                    145: #if TESTING
                    146:                 else
                    147:                    DbgPrint("Device is Black & White.\n");
                    148: #endif
                    149:                 break;
                    150: 
                    151:             case VARIABLEPAPER:
                    152:                GetWord(szWord, sizeof(szWord), pdata);
                    153:                if (!(strncmp(szWord, "True", 4)))
                    154:                 {
                    155:                     pntpd->flFlags |= VARIABLE_PAPER;
                    156: #if TESTING
                    157:                    DbgPrint("Device supports Variable Paper.\n");
                    158: #endif
                    159:                 }
                    160: #if TESTING
                    161:                 else
                    162:                    DbgPrint("Device does not support Variable Paper.\n");
                    163: #endif
                    164:                 break;
                    165: 
                    166:             case ENDOFFILE:
                    167:                 GetWord(szWord, sizeof(szWord), pdata);
                    168:                 if (!(strncmp(szWord, "False", 5)))
                    169:                 {
                    170:                     pntpd->flFlags |= NO_ENDOFFILE;
                    171: #if TESTING
                    172:                     DbgPrint("Device does not want Ctrl-D.\n");
                    173: #endif
                    174:                 }
                    175:                 else
                    176: {
                    177:                     pntpd->flFlags &= ~NO_ENDOFFILE;
                    178: #if TESTING
                    179:                     DbgPrint("Device does want Ctrl-D.\n");
                    180: #endif
                    181: }
                    182: 
                    183:                 break;
                    184: 
                    185:             case DEFAULTMANUALFEED:
                    186:                 GetWord(szWord, sizeof(szWord), pdata);
                    187:                if (!(strncmp(szWord, "True", 4)))
                    188:                 {
                    189:                     pntpd->flFlags |= MANUALFEED_ON;
                    190: #if TESTING
                    191:                    DbgPrint("Device defaults to Manual Feed.\n");
                    192: #endif
                    193:                 }
                    194: #if TESTING
                    195:                 else
                    196:                    DbgPrint("Device does not default to Manual Feed.\n");
                    197: #endif
                    198:                 break;
                    199: 
                    200:             case PROTOCOLS:
                    201:                 ParseProtocols(pdata, pntpd);
                    202:                 break;
                    203: 
                    204:             case NICKNAME:
                    205:                 ptmp->cbPrinterName = GetString(ptmp->szPrinterName, pdata);
                    206: 
                    207:                 // make room for UNICODE printer name.
                    208: 
                    209:                 ptmp->cbPrinterName *= 2;
                    210: #if TESTING
                    211:                DbgPrint("PrinterName = %s\n", ptmp->szPrinterName);
                    212: #endif
                    213:                 break;
                    214: 
                    215:             case PRTVM:
                    216:                 // fill in the free virtual memory in kilobytes.
                    217: 
                    218:                 i = GetNumber(pdata);
                    219:                 pntpd->cbFreeVM = (i >> 10);
                    220: #if TESTING
                    221:                DbgPrint("FreeVM = %d KB.\n", pntpd->cbFreeVM);
                    222: #endif
                    223:                 break;
                    224: 
                    225:             case LANGUAGELEVEL:
                    226:                 // fill in the language level.  default to level 1 if
                    227:                 // level 2 is not specified.
                    228: 
                    229:                 i = GetNumber(pdata);
                    230: 
                    231:                 if (i != 2)
                    232:                     i = 1;
                    233: 
                    234:                 pntpd->LangLevel = (DWORD)i;
                    235: #if TESTING
                    236:                DbgPrint("LanguageLevel = %d.\n", pntpd->LangLevel);
                    237: #endif
                    238:                 break;
                    239: 
                    240:             case DEFAULTRESOLUTION:
                    241:                 pntpd->iDefResolution = (USHORT)GetNumber(pdata);
                    242: #if TESTING
                    243:                DbgPrint("DefResolution = %d.\n", pntpd->iDefResolution);
                    244: #endif
                    245:                 break;
                    246: 
                    247:             case SETRESOLUTION:
                    248:             case RESOLUTION:
                    249:                 // increment the resolution count.  for most printers, which
                    250:                 // do not support this, pntpd->cResolutions will be zero.
                    251:                 // this obviously means to use the defaultresolution.
                    252: 
                    253:                 i = pntpd->cResolutions;
                    254:                 i++;
                    255:                 if (i > MAX_RESOLUTIONS)
                    256:                 {
                    257:                     RIP("Too Many Resolutions\n");
                    258:                     break;
                    259:                 }
                    260:                 pntpd->cResolutions = (USHORT)i;
                    261: 
                    262:                 // get the resolution itself.
                    263: 
                    264:                 i--;
                    265:                 ptmp->siResolutions[i].usIndex = (USHORT)GetNumber(pdata);
                    266: #if TESTING
                    267:                DbgPrint("Resolution Value = %d\n",
                    268:                          ptmp->siResolutions[i].usIndex);
                    269: #endif
                    270:                 // now get the string to send to the printer to set the
                    271:                 // resolution.
                    272: 
                    273:                 GetString(ptmp->siResolutions[i].szString, pdata);
                    274:                 break;
                    275: 
                    276:             case SCREENFREQ:
                    277:                 // the screen frequency is stored within quotes.
                    278:                 // advance to first quotation mark, then one character past.
                    279: 
                    280:                 while (*(pdata->szLine) != '"')
                    281:                     pdata->szLine++;
                    282:                 pdata->szLine++;
                    283: 
                    284:                 pntpd->iScreenFreq = (USHORT)GetFloat(10, pdata);
                    285: #if TESTING
                    286:                DbgPrint("ScreenFrequency * 10 = %d\n", pntpd->iScreenFreq);
                    287: #endif
                    288:                 break;
                    289: 
                    290:             case SCREENANGLE:
                    291:                 // the screen angle is stored within quotes.
                    292:                 // advance to first quotation mark, then one character past.
                    293: 
                    294:                 while (*(pdata->szLine) != '"')
                    295:                     pdata->szLine++;
                    296:                 pdata->szLine++;
                    297: 
                    298:                 pntpd->iScreenAngle = (USHORT)GetFloat(10, pdata);
                    299: #if TESTING
                    300:                DbgPrint("ScreenAngle * 10 = %d\n", pntpd->iScreenAngle);
                    301: #endif
                    302:                 break;
                    303: 
                    304:             case TRANSFER:
                    305:                 // GetOptionIndex will get the string defining the type
                    306:                 // of transfer function.  Normalized is the one we
                    307:                 // care about.
                    308: 
                    309:                 i = GetOptionIndex(SecondKeyTable, pdata);
                    310:                 if (i == NORMALIZED)
                    311:                 {
                    312:                     ptmp->cbTransferNorm = GetString(ptmp->szTransferNorm, pdata);
                    313: #if TESTING
                    314:                    DbgPrint("TransferNormalized = %s\n",
                    315:                              ptmp->szTransferNorm);
                    316: #endif
                    317:                 }
                    318:                 else if (i == NORM_INVERSE)
                    319:                 {
                    320:                     ptmp->cbInvTransferNorm = GetString(ptmp->szInvTransferNorm, pdata);
                    321: #if TESTING
                    322:                    DbgPrint("InvTransferNormalized = %s\n",
                    323:                              ptmp->szInvTransferNorm);
                    324: #endif
                    325:                 }
                    326: 
                    327:                 break;
                    328: 
                    329:             case DUPLEX:
                    330:                 // GetOptionIndex will get the string defining the type
                    331:                 // of duplex function.
                    332: 
                    333:                 i = GetOptionIndex(SecondKeyTable, pdata);
                    334: 
                    335:                 switch (i)
                    336:                 {
                    337:                     case OPTION_FALSE:
                    338:                         ptmp->cbDuplexNone = GetString(ptmp->szDuplexNone, pdata);
                    339: #if TESTING
                    340:                         DbgPrint("szDuplexNone = %s.\n", ptmp->szDuplexNone);
                    341: #endif
                    342:                         break;
                    343: 
                    344:                     case OPTION_TRUE:
                    345:                         ptmp->cbDuplexNoTumble = GetString(ptmp->szDuplexNoTumble, pdata);
                    346: #if TESTING
                    347:                         DbgPrint("szDuplexNoTumble = %s.\n", ptmp->szDuplexNoTumble);
                    348: #endif
                    349:                         break;
                    350: 
                    351:                     case OPTION_NONE:
                    352:                         ptmp->cbDuplexNone = GetString(ptmp->szDuplexNone, pdata);
                    353: #if TESTING
                    354:                         DbgPrint("szDuplexNone = %s.\n", ptmp->szDuplexNone);
                    355: #endif
                    356:                         break;
                    357: 
                    358:                     case DUPLEX_TUMBLE:
                    359:                         ptmp->cbDuplexTumble = GetString(ptmp->szDuplexTumble, pdata);
                    360: #if TESTING
                    361:                         DbgPrint("szDuplexTumble = %s.\n", ptmp->szDuplexTumble);
                    362: #endif
                    363:                         break;
                    364: 
                    365:                     case DUPLEX_NO_TUMBLE:
                    366:                         ptmp->cbDuplexNoTumble = GetString(ptmp->szDuplexNoTumble, pdata);
                    367: #if TESTING
                    368:                         DbgPrint("szDuplexNoTumble = %s.\n", ptmp->szDuplexNoTumble);
                    369: #endif
                    370:                         break;
                    371:                 }
                    372: 
                    373:                 break;
                    374: 
                    375:             case COLLATE:
                    376:                 // GetOptionIndex will get the string defining the type
                    377:                 // of collate function.
                    378: 
                    379:                 i = GetOptionIndex(SecondKeyTable, pdata);
                    380:                 if (i == OPTION_TRUE)
                    381:                 {
                    382:                     ptmp->cbCollateOn = GetString(ptmp->szCollateOn, pdata);
                    383: #if TESTING
                    384:                    DbgPrint("CollateOn = %s\n",
                    385:                              ptmp->szCollateOn);
                    386: #endif
                    387:                 }
                    388:                 else if (i == OPTION_FALSE)
                    389:                 {
                    390:                     ptmp->cbCollateOff = GetString(ptmp->szCollateOff, pdata);
                    391: #if TESTING
                    392:                    DbgPrint("CollateOff = %s\n",
                    393:                              ptmp->szCollateOff);
                    394: #endif
                    395:                 }
                    396: 
                    397:                 break;
                    398: 
                    399:             case DEFAULTPAGESIZE:
                    400:                 // GetOptionIndex, will get the string defining the defaultpagesize,
                    401:                 // and return the corresponding value from PaperTable.
                    402: 
                    403:                 GetOptionString(ptmp->szDefaultForm, sizeof(ptmp->szDefaultForm),
                    404:                             pdata);
                    405: 
                    406: #if TESTING
                    407:                 DbgPrint("DefaultForm = %s.\n", ptmp->szDefaultForm);
                    408: #endif
                    409:                 break;
                    410: 
                    411:             case PAGESIZE:
                    412:                 // increment the paper size count.
                    413: 
                    414:                 i = pntpd->cPSForms;
                    415: 
                    416:                 if (i >= MAX_PAPERSIZES)
                    417:                 {
                    418:                     RIP("Too Many PaperSizes.\n");
                    419:                     break;
                    420:                 }
                    421: 
                    422:                 pntpd->cPSForms++;
                    423: 
                    424:                 // get the form name.
                    425: 
                    426:                 GetOptionString(ptmp->FormEntry[i].szName,
                    427:                             sizeof(ptmp->FormEntry[i].szName), pdata);
                    428: 
                    429:                 // now get the form invocation string to send to the printer.
                    430: 
                    431:                 GetString(ptmp->FormEntry[i].szInvocation, pdata);
                    432: 
                    433:                 break;
                    434: 
                    435:             case PAGEREGION:
                    436:                 // increment the page region count.
                    437: 
                    438:                 i = pntpd->cPageRegions;
                    439: 
                    440:                 if (i >= MAX_PAPERSIZES)
                    441:                 {
                    442:                     RIP("Too Many PageRegions.\n");
                    443:                     break;
                    444:                 }
                    445:                 pntpd->cPageRegions++;
                    446: 
                    447:                 // get the form name, and the invocation string to
                    448:                 // set the page region.
                    449: 
                    450:                 GetOptionString(ptmp->PageRegion[i].szName,
                    451:                             sizeof(ptmp->PageRegion[i].szName), pdata);
                    452: 
                    453: #if TESTING
                    454:                DbgPrint("PageRegion %s.\n", ptmp->PageRegion[i].szName);
                    455: #endif
                    456: 
                    457:                 // now get the pageregion invocation string.
                    458: 
                    459:                 GetString(ptmp->PageRegion[i].szInvocation, pdata);
                    460: 
                    461:                 break;
                    462: 
                    463:             case IMAGEABLEAREA:
                    464:                 // increment the imageablearea count.
                    465: 
                    466:                 i = ptmp->cImageableAreas;
                    467: 
                    468:                 if (i >= MAX_PAPERSIZES)
                    469:                 {
                    470:                     RIP("Too Many ImageableAreas.\n");
                    471:                     break;
                    472:                 }
                    473: 
                    474:                 ptmp->cImageableAreas++;
                    475: 
                    476:                 // get the form name.
                    477: 
                    478:                 GetOptionString(ptmp->ImageableArea[i].szForm,
                    479:                                 sizeof(ptmp->ImageableArea[i].szForm),
                    480:                                 pdata);
                    481: 
                    482:                 // now get the rectangle of the imageablearea.
                    483: 
                    484:                 GetImageableArea(&ptmp->ImageableArea[i].rect, pdata);
                    485: #if TESTING
                    486:                DbgPrint("ImageableArea %s = %d %d %d %d\n",
                    487:                          ptmp->ImageableArea[i].szForm,
                    488:                          ptmp->ImageableArea[i].rect.left,
                    489:                          ptmp->ImageableArea[i].rect.top,
                    490:                          ptmp->ImageableArea[i].rect.right,
                    491:                          ptmp->ImageableArea[i].rect.bottom);
                    492: #endif
                    493:                 break;
                    494: 
                    495:             case PAPERDIMENSION:
                    496:                 // increment the paperdimension count.
                    497: 
                    498:                 i = ptmp->cPaperDimensions;
                    499: 
                    500:                 if (i >= MAX_PAPERSIZES)
                    501:                 {
                    502:                     RIP("Too Many PaperDimensions.\n");
                    503:                     break;
                    504:                 }
                    505: 
                    506:                 ptmp->cPaperDimensions++;
                    507: 
                    508:                 GetOptionString(ptmp->PaperDimension[i].szForm,
                    509:                                 sizeof(ptmp->PaperDimension[i].szForm),
                    510:                                 pdata);
                    511: 
                    512:                 // now get the rectangle of the paper itself.
                    513: 
                    514:                 GetDimension(&ptmp->PaperDimension[i], pdata);
                    515: #if TESTING
                    516:                DbgPrint("PaperDimension %s = %d %d\n",
                    517:                          ptmp->PaperDimension[i].szForm,
                    518:                          ptmp->PaperDimension[i].sizl.cx,
                    519:                          ptmp->PaperDimension[i].sizl.cy);
                    520: #endif
                    521:                 break;
                    522: 
                    523:             case DEFAULTOUTPUTBIN:
                    524:                 GetOptionString(ptmp->szDefaultOutputBin,
                    525:                                 sizeof(ptmp->szDefaultOutputBin), pdata);
                    526: 
                    527: #if TESTING
                    528:                DbgPrint("DefaultOutputBin = %s\n", ptmp->szDefaultOutputBin);
                    529: #endif
                    530:                 break;
                    531: 
                    532: 
                    533:             case OUTPUTBIN:
                    534:                 // increment the output bin count.
                    535: 
                    536:                 i = pntpd->cOutputBins;
                    537:                 i++;
                    538:                 if (i > MAX_BINS)
                    539:                 {
                    540:                     RIP("Too Many OutputBins.\n");
                    541:                     break;
                    542:                 }
                    543:                 pntpd->cOutputBins = (USHORT)i;
                    544: 
                    545:                 i--;
                    546: 
                    547:                 GetOptionString(ptmp->siOutputBin[i].szName,
                    548:                                 sizeof(ptmp->siOutputBin[i].szName), pdata);
                    549: #if TESTING
                    550:                DbgPrint("OutputBin Name = %s\n", ptmp->siOutputBin[i].szName);
                    551: #endif
                    552: 
                    553:                 // now get the string to send to the printer to set the
                    554:                 // outputbin.
                    555: 
                    556:                 GetString(ptmp->siOutputBin[i].szInvocation, pdata);
                    557:                 break;
                    558: 
                    559:             case DEFAULTINPUTSLOT:
                    560:                 GetOptionString(ptmp->szDefaultInputSlot,
                    561:                                 sizeof(ptmp->szDefaultInputSlot), pdata);
                    562: 
                    563: #if TESTING
                    564:                DbgPrint("DefaultInputSlot = %s\n", ptmp->szDefaultInputSlot);
                    565: #endif
                    566:                 break;
                    567: 
                    568: 
                    569:             case INPUTSLOT:
                    570:                 // increment the output bin count.
                    571: 
                    572:                 i = pntpd->cInputSlots;
                    573:                 i++;
                    574:                 if (i > MAX_BINS)
                    575:                 {
                    576:                     RIP("Too Many InputSlots.\n");
                    577:                     break;
                    578:                 }
                    579:                 pntpd->cInputSlots = (USHORT)i;
                    580: 
                    581:                 i--;
                    582: 
                    583:                 GetOptionString(ptmp->siInputSlot[i].szName,
                    584:                                 sizeof(ptmp->siInputSlot[i].szName), pdata);
                    585: 
                    586: #if TESTING
                    587:                DbgPrint("InputSlot Name = %s\n", ptmp->siInputSlot[i].szName);
                    588: #endif
                    589: 
                    590:                 // now get the string to send to the printer to set the
                    591:                 // inputslot.
                    592: 
                    593:                 GetString(ptmp->siInputSlot[i].szInvocation, pdata);
                    594:                 break;
                    595: 
                    596:             case MANUALFEED:
                    597:                 // GetOptionIndex will get the string defining the type
                    598:                 // of ManualFeed function.
                    599: 
                    600:                 i = GetOptionIndex(SecondKeyTable, pdata);
                    601: 
                    602:                 if (i == OPTION_TRUE)
                    603:                 {
                    604:                     // get and save the string to set manual feed to TRUE
                    605:                     // for the given printer.
                    606: 
                    607:                     ptmp->cbManualTRUE = GetString(ptmp->szManualTRUE, pdata);
                    608:                 }
                    609:                 else if (i == OPTION_FALSE)
                    610:                 {
                    611:                     // get and save the string to set manual feed to FALSE
                    612:                     // for the given printer.
                    613: 
                    614:                     ptmp->cbManualFALSE = GetString(ptmp->szManualFALSE, pdata);
                    615:                 }
                    616: 
                    617:                 break;
                    618: 
                    619:             case DEFAULTFONT:
                    620:                 // GetOptionIndex, will get the string defining the defaultfont,
                    621:                 // and return the corresponding value from FontTable.
                    622: 
                    623:                 i = GetOptionIndex(FontTable, pdata);
                    624:                 pntpd->usDefaultFont = (USHORT)i;
                    625: #if TESTING
                    626:                DbgPrint("DefaultFont = %d\n", i);
                    627: #endif
                    628:                 break;
                    629: 
                    630:             case DEVICE_FONT:
                    631:                 // get the index of the font.
                    632: 
                    633:                 j = GetOptionIndex(FontTable, pdata);
                    634: 
                    635:                 if (j == TK_UNDEFINED)
                    636:                 {
                    637: #if TESTING
                    638:                     DbgPrint("ParsePPD: font not found.\n");
                    639: #endif
                    640:                     break;
                    641:                 }
                    642: 
                    643:                 // increment the font counter if the font was valid.
                    644: 
                    645:                 i = pntpd->cFonts;
                    646:                 i++;
                    647: 
                    648:                 if (i > MAX_FONTS)
                    649:                 {
                    650:                     RIP("Too Many Fonts.\n");
                    651:                     break;
                    652:                 }
                    653: 
                    654:                 pntpd->cFonts = (USHORT)i;
                    655: 
                    656:                 // GetOptionIndex, will get the string defining the font,
                    657:                 // and return the corresponding value from FontTable.
                    658: 
                    659:                 i--;
                    660: 
                    661:                 ptmp->bFonts[i] = (BYTE)j;
                    662: #if TESTING
                    663:                DbgPrint("Font Value = %d\n", j);
                    664: #endif
                    665:                 break;
                    666: 
                    667:             default:
                    668:                 break;
                    669:         }
                    670:     }
                    671: }
                    672: 
                    673: 
                    674: //--------------------------------------------------------------------------
                    675: //
                    676: // VOID BuildNTPD(pntpd, ptmp);
                    677: // PNTPD        pntpd;
                    678: // PTMP_NTPD    ptmp;
                    679: //
                    680: // Fills in the NTPD structure with values derived from the TMP_NTPD
                    681: // structure.
                    682: //
                    683: // Returns:
                    684: //   This routine returns no value.
                    685: //
                    686: // History:
                    687: //   25-Mar-1991    -by-    Kent Settle    (kentse)
                    688: //  Wrote it.
                    689: //--------------------------------------------------------------------------
                    690: 
                    691: VOID BuildNTPD(pntpd, ptmp)
                    692: PNTPD       pntpd;
                    693: PTMP_NTPD   ptmp;
                    694: {
                    695:     DWORD           i, j;
                    696:     BYTE           *pfont;
                    697:     PSRESOLUTION   *pRes;
                    698:     PSFORM         *pForm;
                    699:     PSOUTPUTBIN    *pBin;
                    700:     PSINPUTSLOT    *pSlot;
                    701: 
                    702:     // start by adding the printer name to the end of the NTPD structure.
                    703:     // the printer name is stored as a UNICODE string, so it needs to be
                    704:     // WCHAR aligned.
                    705: 
                    706: #if SIZE_TEST
                    707:     DbgPrint("Entering BuildNTPD: cjThis = %d.\n", pntpd->cjThis);
                    708: #endif
                    709: 
                    710:     pntpd->cjThis = WCHARALIGN(pntpd->cjThis);
                    711: 
                    712: #if DBG
                    713:     // make sure alignment is proper.
                    714: 
                    715:     ASSERTPS(((pntpd->cjThis % sizeof(WCHAR)) == 0),
                    716:              "pntpd->lowszPrinterName not properly aligned.\n");
                    717: #endif
                    718: 
                    719:     pntpd->lowszPrinterName = pntpd->cjThis;
                    720: 
                    721:     strcpy2WChar((PWSTR)((PSTR)pntpd + pntpd->lowszPrinterName),
                    722:                  ptmp->szPrinterName);
                    723: 
                    724: #if TESTING
                    725:     DbgPrint("PrinterName = %ws\n",
                    726:              (PWSTR)((PSTR)pntpd + pntpd->lowszPrinterName));
                    727: #endif
                    728: 
                    729:     // now add the set resolution strings to the end of the structure,
                    730:     // if there are any to add.  it is worth noting how these are stored
                    731:     // in the NTPD structure.  an array of cResolutions PSRESOLUTION
                    732:     // structures are stored at the end of the NTPD structure.  within
                    733:     // each PSRESOLUTION structure is an offset to the string corresponding
                    734:     // to the resolution in question.
                    735: 
                    736:     // the start of the PSRESOLUTION array must be DWORD aligned.
                    737: 
                    738:     pntpd->cjThis += ptmp->cbPrinterName;
                    739:     pntpd->cjThis = DWORDALIGN(pntpd->cjThis);
                    740: 
                    741: #if DBG
                    742:     // make sure alignment is proper.
                    743: 
                    744:     ASSERTPS(((pntpd->cjThis % sizeof(DWORD)) == 0),
                    745:              "pntpd->loResolution not properly aligned.\n");
                    746: #endif
                    747: 
                    748:     pntpd->loResolution = pntpd->cjThis;
                    749: 
                    750: #if SIZE_TEST
                    751:     DbgPrint("post cbPrinterName: cjThis = %d.\n", pntpd->cjThis);
                    752: #endif
                    753: 
                    754:     if (pntpd->cResolutions != 0)
                    755:     {
                    756:         // add the PSRESOLUTION array to the end of the NTPD structure.
                    757: 
                    758:         pntpd->cjThis += pntpd->cResolutions * sizeof(PSRESOLUTION);
                    759: 
                    760:         pRes = (PSRESOLUTION *)((CHAR *)pntpd + pntpd->loResolution);
                    761: 
                    762:         // for each resolution, fill in the PSRESOLUTION structure.
                    763:         // then add the string itself to the end of the NTPD structure.
                    764: 
                    765:         for (i = 0; i < (DWORD)pntpd->cResolutions; i++)
                    766:         {
                    767:             pRes[i].iValue = (DWORD)ptmp->siResolutions[i].usIndex;
                    768:             pRes[i].loInvocation = pntpd->cjThis;
                    769: 
                    770:             j = szLength(ptmp->siResolutions[i].szString);
                    771:             memcpy((CHAR *)pntpd + pntpd->cjThis,
                    772:                    ptmp->siResolutions[i].szString, j);
                    773:             pntpd->cjThis += j;
                    774:         }
                    775:     }
                    776: 
                    777: #if SIZE_TEST
                    778:     DbgPrint("post resolutions: cjThis = %d.\n", pntpd->cjThis);
                    779: #endif
                    780: 
                    781:     // add the transfernormalized string to the end of the structure.
                    782:     // check to make sure we have a string to copy.
                    783: 
                    784:     i = (USHORT)ptmp->cbTransferNorm;
                    785: 
                    786:     if (i != 0)
                    787:     {
                    788:         pntpd->loszTransferNorm = pntpd->cjThis;
                    789:         pntpd->cjThis += i;
                    790: 
                    791:         memcpy((CHAR *)pntpd + pntpd->loszTransferNorm,
                    792:                ptmp->szTransferNorm, i);
                    793:     }
                    794: 
                    795: #if SIZE_TEST
                    796:     DbgPrint("post cbTransferNorm: cjThis = %d.\n", pntpd->cjThis);
                    797: #endif
                    798: 
                    799: #if TESTING
                    800:     if (i != 0)
                    801:        DbgPrint("Transfer Normalized Not Found.\n");
                    802:     else
                    803:        DbgPrint("Transfer Normalized = %s\n", ptmp->szTransferNorm);
                    804: #endif
                    805: 
                    806:     // add the inverse transfernormalized string to the end of the structure.
                    807:     // check to make sure we have a string to copy.
                    808: 
                    809:     if (i = ptmp->cbInvTransferNorm)
                    810:     {
                    811:         pntpd->loszInvTransferNorm = pntpd->cjThis;
                    812:         pntpd->cjThis += i;
                    813: 
                    814:         memcpy((CHAR *)pntpd + pntpd->loszInvTransferNorm,
                    815:                ptmp->szInvTransferNorm, i);
                    816:     }
                    817: 
                    818: #if SIZE_TEST
                    819:     DbgPrint("post cbInvTransferNorm: cjThis = %d.\n", pntpd->cjThis);
                    820: #endif
                    821: 
                    822: #if TESTING
                    823:     if (i != 0)
                    824:        DbgPrint("Inverse Transfer Normalized Not Found.\n");
                    825:     else
                    826:        DbgPrint("Inverse Transfer Normalized = %s\n", ptmp->szTransferNorm);
                    827: #endif
                    828: 
                    829:     // fill in the default form name.
                    830: 
                    831:     pntpd->loDefaultForm = pntpd->cjThis;
                    832:     strcpy((CHAR *)pntpd + pntpd->loDefaultForm, ptmp->szDefaultForm);
                    833:     pntpd->cjThis += szLength(ptmp->szDefaultForm);
                    834: 
                    835:     // add the form names list to the end of the structure.
                    836: 
                    837:     pntpd->cjThis = DWORDALIGN(pntpd->cjThis);
                    838: 
                    839: #if SIZE_TEST
                    840:     DbgPrint("post szDefaultForm: cjThis = %d.\n", pntpd->cjThis);
                    841: #endif
                    842: 
                    843: #if DBG
                    844:     // make sure alignment is proper.
                    845: 
                    846:     ASSERTPS(((pntpd->cjThis % sizeof(DWORD)) == 0),
                    847:              "pntpd->loPSFORMArray not properly aligned.\n");
                    848: #endif
                    849: 
                    850:     pntpd->loPSFORMArray = pntpd->cjThis;
                    851:     pntpd->cjThis += pntpd->cPSForms * sizeof(PSFORM);
                    852: 
                    853: #if SIZE_TEST
                    854:     DbgPrint("post cPSForms: cjThis = %d.\n", pntpd->cjThis);
                    855: #endif
                    856: 
                    857:     pForm = (PSFORM *)((CHAR *)pntpd + pntpd->loPSFORMArray);
                    858: 
                    859:     // for each form, fill in the offset to the form name string, the
                    860:     // offset to the invocation string, then the strings themselves.
                    861: 
                    862:     for (i = 0; i < pntpd->cPSForms; i++)
                    863:     {
                    864:         pForm[i].loFormName = pntpd->cjThis;
                    865:         strcpy((CHAR *)pntpd + pntpd->cjThis, ptmp->FormEntry[i].szName);
                    866:         pntpd->cjThis += szLength(ptmp->FormEntry[i].szName);
                    867: 
                    868:         pForm[i].loSizeInvo = pntpd->cjThis;
                    869:         strcpy((CHAR *)pntpd + pntpd->cjThis, ptmp->FormEntry[i].szInvocation);
                    870:         pntpd->cjThis += szLength(ptmp->FormEntry[i].szInvocation);
                    871: 
                    872: #if TESTING
                    873:         DbgPrint("FormEntry %s = %s.\n", ptmp->FormEntry[i].szName,
                    874:                  ptmp->FormEntry[i].szInvocation);
                    875: #endif
                    876:     }
                    877: 
                    878: #if SIZE_TEST
                    879:     DbgPrint("post all forms: cjThis = %d.\n", pntpd->cjThis);
                    880: #endif
                    881: 
                    882:     // fill in the page region information. an offset to each string is set
                    883:     // in the corresponding PSFORM struct. then add the string itself to the
                    884:     // end of the NTPD structure.
                    885: 
                    886:     for (i = 0; i < pntpd->cPageRegions; i++)
                    887:     {
                    888:         for (j = 0; j < pntpd->cPSForms; j++)
                    889:         {
                    890:             if (!(NameComp((CHAR *)pntpd + pForm[j].loFormName,
                    891:                          ptmp->PageRegion[i].szName)))
                    892:             {
                    893:                 pForm[j].loRegionInvo = pntpd->cjThis;
                    894:                 strcpy((CHAR *)pntpd + pntpd->cjThis,
                    895:                        ptmp->PageRegion[i].szInvocation);
                    896:                 pntpd->cjThis += szLength(ptmp->PageRegion[i].szInvocation);
                    897: 
                    898: #if TESTING
                    899:     DbgPrint("PageRegion[%d] = %s\n", i, ptmp->PageRegion[i].szName);
                    900: #endif
                    901:             }
                    902:         }
                    903:     }
                    904: 
                    905: #if SIZE_TEST
                    906:     DbgPrint("post page regions: cjThis = %d.\n", pntpd->cjThis);
                    907: #endif
                    908: 
                    909:     // fill in the imageablearea information.  an RECTL for each form is
                    910:     // included within the PSFORM struct.
                    911: 
                    912:     for (i = 0; i < ptmp->cImageableAreas; i++)
                    913:     {
                    914:         for (j = 0; j < pntpd->cPSForms; j++)
                    915:         {
                    916:             if (!(NameComp((CHAR *)pntpd + pForm[j].loFormName,
                    917:                          ptmp->ImageableArea[i].szForm)))
                    918:             {
                    919:                 pForm[j].imagearea = ptmp->ImageableArea[i].rect;
                    920: #if TESTING
                    921:     DbgPrint("ImageableArea %s = %d %d %d %d.\n",
                    922:              ptmp->PageRegion[i].szName,
                    923:              pForm[j].imagearea.left, pForm[j].imagearea.top,
                    924:              pForm[j].imagearea.right, pForm[j].imagearea.bottom);
                    925: #endif
                    926:             }
                    927:         }
                    928:     }
                    929: 
                    930: #if SIZE_TEST
                    931:     DbgPrint("post imageableareas: cjThis = %d.\n", pntpd->cjThis);
                    932: #endif
                    933: 
                    934:     // fill in the paper dimension information.  a SIZEL for each form is
                    935:     // included within the PSFORM struct.
                    936: 
                    937:     for (i = 0; i < ptmp->cPaperDimensions; i++)
                    938:     {
                    939:         for (j = 0; j < pntpd->cPSForms; j++)
                    940:         {
                    941:             if (!(NameComp((CHAR *)pntpd + pForm[j].loFormName,
                    942:                          ptmp->PaperDimension[i].szForm)))
                    943:             {
                    944:                 pForm[j].sizlPaper = ptmp->PaperDimension[i].sizl;
                    945: #if TESTING
                    946:     DbgPrint("PaperDimension %s = %d %d.\n",
                    947:              ptmp->PaperDimension[i].szForm,
                    948:              pForm[j].sizlPaper.cx, pForm[j].sizlPaper.cy);
                    949: #endif
                    950:             }
                    951:         }
                    952:     }
                    953: 
                    954: #if SIZE_TEST
                    955:     DbgPrint("post paper dimensions: cjThis = %d.\n", pntpd->cjThis);
                    956: #endif
                    957: 
                    958:     // now add the outputbin strings to the end of the structure,
                    959:     // if there are any to add.  it is worth noting how these are stored
                    960:     // in the NTPD structure.  an array of cOutputBins PSOUTPUTBIN
                    961:     // structures are stored at the end of the NTPD structure.  within
                    962:     // each PSOUTPUTBIN structure are offsets to the strings corresponding
                    963:     // to the output bin and invocation.  if there is only the default
                    964:     // outputbin defined, cOutputBins will be zero.  otherwise it is assumed
                    965:     // there will be at least two output bins defined.  if there is only one
                    966:     // defined, it will be the same as the default.
                    967: 
                    968:     pntpd->loDefaultBin = pntpd->cjThis;
                    969:     strcpy((CHAR *)pntpd + pntpd->loDefaultBin, ptmp->szDefaultOutputBin);
                    970:     pntpd->cjThis += szLength(ptmp->szDefaultOutputBin);
                    971:     pntpd->cjThis = DWORDALIGN(pntpd->cjThis);
                    972: 
                    973: #if SIZE_TEST
                    974:     DbgPrint("post szDefaultOutputBin: cjThis = %d.\n", pntpd->cjThis);
                    975: #endif
                    976: 
                    977:     if (pntpd->cOutputBins > 0)
                    978:     {
                    979: #if DBG
                    980:     // make sure alignment is proper.
                    981: 
                    982:     ASSERTPS(((pntpd->cjThis % sizeof(DWORD)) == 0),
                    983:              "pntpd->loPSOutputBins not properly aligned.\n");
                    984: #endif
                    985: 
                    986:         // add the PSOUTPUTBIN array to the end of the NTPD structure.
                    987: 
                    988:         pntpd->loPSOutputBins = pntpd->cjThis;
                    989: 
                    990:         pntpd->cjThis += pntpd->cOutputBins * sizeof(PSOUTPUTBIN);
                    991: 
                    992: #if SIZE_TEST
                    993:     DbgPrint("post cOutputBins: cjThis = %d.\n", pntpd->cjThis);
                    994: #endif
                    995: 
                    996:         pBin = (PSOUTPUTBIN *)((CHAR *)pntpd + pntpd->loPSOutputBins);
                    997: 
                    998:         // for each outputbin, fill in the PSOUTPUTBIN structure.
                    999:         // then add the string itself to the end of the NTPD structure.
                   1000: 
                   1001:         for (i = 0; i < pntpd->cOutputBins; i++)
                   1002:         {
                   1003:             // copy the output bin name and the invocation string.
                   1004: 
                   1005:             pBin[i].loBinName = pntpd->cjThis;
                   1006:             strcpy((CHAR *)pntpd + pntpd->cjThis, ptmp->siOutputBin[i].szName);
                   1007:             pntpd->cjThis += szLength(ptmp->siOutputBin[i].szName);
                   1008: 
                   1009:             pBin[i].loBinInvo = pntpd->cjThis;
                   1010:             strcpy((CHAR *)pntpd + pntpd->cjThis,
                   1011:                    ptmp->siOutputBin[i].szInvocation);
                   1012:             pntpd->cjThis += szLength(ptmp->siOutputBin[i].szInvocation);
                   1013: 
                   1014: #if TESTING
                   1015:            DbgPrint("OutputBin[%d] = %s\n", i,
                   1016:                      (CHAR *)pntpd + pBin[i].loBinName);
                   1017: #endif
                   1018:         }
                   1019:     }
                   1020: 
                   1021: #if SIZE_TEST
                   1022:     DbgPrint("post all output bins: cjThis = %d.\n", pntpd->cjThis);
                   1023: #endif
                   1024: 
                   1025:     // now add the inputslot strings to the end of the structure,
                   1026:     // if there are any to add.  it is worth noting how these are stored
                   1027:     // in the NTPD structure.  an array of cInputSlots PSINPUTSLOT
                   1028:     // structures are stored at the end of the NTPD structure.  within
                   1029:     // each PSINPUTSLOT structure are offsets to the strings corresponding
                   1030:     // to the slot name and invocation.  if there is only the default inputslot
                   1031:     // defined, cInputSlots will be zero.  otherwise it is assumed there
                   1032:     // will be at least two input slots defined.  if there is only one
                   1033:     // defined, it will be the same as the default.
                   1034: 
                   1035:     pntpd->loDefaultSlot = pntpd->cjThis;
                   1036:     strcpy((CHAR *)pntpd + pntpd->loDefaultSlot, ptmp->szDefaultInputSlot);
                   1037:     pntpd->cjThis += szLength(ptmp->szDefaultInputSlot);
                   1038:     pntpd->cjThis = DWORDALIGN(pntpd->cjThis);
                   1039: 
                   1040: #if SIZE_TEST
                   1041:     DbgPrint("post szDefaultInputSlot: cjThis = %d.\n", pntpd->cjThis);
                   1042: #endif
                   1043: 
                   1044:     if (pntpd->cInputSlots > 0)
                   1045:     {
                   1046: #if DBG
                   1047:     // make sure alignment is proper.
                   1048: 
                   1049:     ASSERTPS(((pntpd->cjThis % sizeof(DWORD)) == 0),
                   1050:              "pntpd->loPSInputSlots properly aligned.\n");
                   1051: #endif
                   1052: 
                   1053:         // add the PSINPUTSLOT array to the end of the NTPD structure.
                   1054: 
                   1055:         pntpd->loPSInputSlots = pntpd->cjThis;
                   1056: 
                   1057:         pntpd->cjThis += pntpd->cInputSlots * sizeof(PSINPUTSLOT);
                   1058: 
                   1059: #if SIZE_TEST
                   1060:     DbgPrint("post cInputSlots: cjThis = %d.\n", pntpd->cjThis);
                   1061: #endif
                   1062: 
                   1063:         pSlot = (PSINPUTSLOT *)((CHAR *)pntpd + pntpd->loPSInputSlots);
                   1064: 
                   1065:         // for each inputslot, fill in the PSINPUTSLOT structure.
                   1066:         // then add the string itself to the end of the NTPD structure.
                   1067: 
                   1068:         for (i = 0; i < pntpd->cInputSlots; i++)
                   1069:         {
                   1070:             // copy the input slot name and the invocation string.
                   1071: 
                   1072:             pSlot[i].loSlotName = pntpd->cjThis;
                   1073:             strcpy((CHAR *)pntpd + pntpd->cjThis, ptmp->siInputSlot[i].szName);
                   1074:             pntpd->cjThis += szLength(ptmp->siInputSlot[i].szName);
                   1075: 
                   1076:             pSlot[i].loSlotInvo = pntpd->cjThis;
                   1077:             strcpy((CHAR *)pntpd + pntpd->cjThis,
                   1078:                    ptmp->siInputSlot[i].szInvocation);
                   1079:             pntpd->cjThis += szLength(ptmp->siInputSlot[i].szInvocation);
                   1080: 
                   1081: #if TESTING
                   1082:            DbgPrint("InputSlot[%d] = %s\n", i,
                   1083:                      (CHAR *)pntpd + pSlot[i].loSlotName);
                   1084: #endif
                   1085:         }
                   1086:     }
                   1087: 
                   1088: #if SIZE_TEST
                   1089:     DbgPrint("post all input slots: cjThis = %d.\n", pntpd->cjThis);
                   1090: #endif
                   1091: 
                   1092:     // add the manualfeedtrue string to the end of the structure.
                   1093:     // check to make sure we found a string first.
                   1094: 
                   1095:     if (i = ptmp->cbManualTRUE)
                   1096:     {
                   1097:         pntpd->loszManualFeedTRUE = pntpd->cjThis;
                   1098:         pntpd->cjThis += i;
                   1099: 
                   1100:         memcpy((CHAR *)pntpd + pntpd->loszManualFeedTRUE,
                   1101:                ptmp->szManualTRUE, i);
                   1102:     }
                   1103: 
                   1104: #if SIZE_TEST
                   1105:     DbgPrint("post cbManualTRUE: cjThis = %d.\n", pntpd->cjThis);
                   1106: #endif
                   1107: 
                   1108: #if TESTING
                   1109:     if (i != 0)
                   1110:        DbgPrint("ManualTRUE not found.\n");
                   1111:     else
                   1112:        DbgPrint("ManualTRUE = %s\n", ptmp->szManualTRUE);
                   1113: #endif
                   1114: 
                   1115:     // add the manualfeedfalse string to the end of the structure.
                   1116:     // check to make sure we found a string first.
                   1117: 
                   1118:     if (i = ptmp->cbManualFALSE)
                   1119:     {
                   1120:         pntpd->loszManualFeedFALSE = pntpd->cjThis;
                   1121:         pntpd->cjThis += i;
                   1122: 
                   1123:         memcpy((CHAR *)pntpd + pntpd->loszManualFeedFALSE,
                   1124:                ptmp->szManualFALSE, i);
                   1125:     }
                   1126: 
                   1127: #if SIZE_TEST
                   1128:     DbgPrint("post cbManualFALSE: cjThis = %d.\n", pntpd->cjThis);
                   1129: #endif
                   1130: 
                   1131: #if TESTING
                   1132:     if (i != 0)
                   1133:        DbgPrint("ManualFALSE not found.\n");
                   1134:     else
                   1135:        DbgPrint("ManualFALSE = %s\n", ptmp->szManualFALSE);
                   1136: #endif
                   1137: 
                   1138:     // add the duplex none string to the end of the structure.
                   1139:     // check to make sure we found a string first.
                   1140: 
                   1141:     if (i = ptmp->cbDuplexNone)
                   1142:     {
                   1143:         pntpd->loszDuplexNone = pntpd->cjThis;
                   1144:         pntpd->cjThis += i;
                   1145: 
                   1146:         memcpy((PSTR)pntpd + pntpd->loszDuplexNone, ptmp->szDuplexNone, i);
                   1147:     }
                   1148: 
                   1149: #if SIZE_TEST
                   1150:     DbgPrint("post cbDuplexNone: cjThis = %d.\n", pntpd->cjThis);
                   1151: #endif
                   1152: 
                   1153: #if TESTING
                   1154:     if (i != 0)
                   1155:        DbgPrint("DuplexNone not found.\n");
                   1156:     else
                   1157:        DbgPrint("DuplexNone = %s\n", ptmp->szDuplexNone);
                   1158: #endif
                   1159: 
                   1160:     // add the duplex tumble string to the end of the structure.
                   1161:     // check to make sure we found a string first.
                   1162: 
                   1163:     if (i = ptmp->cbDuplexTumble)
                   1164:     {
                   1165:         pntpd->loszDuplexTumble = pntpd->cjThis;
                   1166:         pntpd->cjThis += i;
                   1167: 
                   1168:         memcpy((PSTR)pntpd + pntpd->loszDuplexTumble, ptmp->szDuplexTumble, i);
                   1169:     }
                   1170: 
                   1171: #if SIZE_TEST
                   1172:     DbgPrint("post cbDuplexTumble: cjThis = %d.\n", pntpd->cjThis);
                   1173: #endif
                   1174: 
                   1175: #if TESTING
                   1176:     if (i != 0)
                   1177:        DbgPrint("DuplexTumble not found.\n");
                   1178:     else
                   1179:        DbgPrint("DuplexTumble = %s\n", ptmp->szDuplexTumble);
                   1180: #endif
                   1181: 
                   1182:     // add the duplex no tumble string to the end of the structure.
                   1183:     // check to make sure we found a string first.
                   1184: 
                   1185:     if (i = ptmp->cbDuplexNoTumble)
                   1186:     {
                   1187:         pntpd->loszDuplexNoTumble = pntpd->cjThis;
                   1188:         pntpd->cjThis += i;
                   1189: 
                   1190:         memcpy((PSTR)pntpd + pntpd->loszDuplexNoTumble, ptmp->szDuplexNoTumble, i);
                   1191:     }
                   1192: 
                   1193: #if SIZE_TEST
                   1194:     DbgPrint("post cbDuplexNoTumble: cjThis = %d.\n", pntpd->cjThis);
                   1195: #endif
                   1196: 
                   1197: #if TESTING
                   1198:     if (i != 0)
                   1199:        DbgPrint("DuplexNoTumble not found.\n");
                   1200:     else
                   1201:        DbgPrint("DuplexNoTumble = %s\n", ptmp->szDuplexNoTumble);
                   1202: #endif
                   1203: 
                   1204:     // add the collate on string to the end of the structure.
                   1205:     // check to make sure we found a string first.
                   1206: 
                   1207:     if (i = ptmp->cbCollateOn)
                   1208:     {
                   1209:         pntpd->loszCollateOn = pntpd->cjThis;
                   1210:         pntpd->cjThis += i;
                   1211: 
                   1212:         memcpy((PSTR)pntpd + pntpd->loszCollateOn, ptmp->szCollateOn, i);
                   1213:     }
                   1214: 
                   1215: #if SIZE_TEST
                   1216:     DbgPrint("post cbCollateOn: cjThis = %d.\n", pntpd->cjThis);
                   1217: #endif
                   1218: 
                   1219: #if TESTING
                   1220:     if (i != 0)
                   1221:        DbgPrint("CollateOn not found.\n");
                   1222:     else
                   1223:        DbgPrint("CollateOn = %s\n", ptmp->szCollateOn);
                   1224: #endif
                   1225: 
                   1226:     // add the collate off string to the end of the structure.
                   1227:     // check to make sure we found a string first.
                   1228: 
                   1229:     if (i = ptmp->cbCollateOff)
                   1230:     {
                   1231:         pntpd->loszCollateOff = pntpd->cjThis;
                   1232:         pntpd->cjThis += i;
                   1233: 
                   1234:         memcpy((PSTR)pntpd + pntpd->loszCollateOff, ptmp->szCollateOff, i);
                   1235:     }
                   1236: 
                   1237: #if SIZE_TEST
                   1238:     DbgPrint("post cbCollateOff: cjThis = %d.\n", pntpd->cjThis);
                   1239: #endif
                   1240: 
                   1241: #if TESTING
                   1242:     if (i != 0)
                   1243:        DbgPrint("CollateOff not found.\n");
                   1244:     else
                   1245:        DbgPrint("CollateOff = %s\n", ptmp->szCollateOff);
                   1246: #endif
                   1247: 
                   1248:     // now add the fonts to the end of the structure, an array of
                   1249:     // pntpd->cFonts BYTES are stored at the end of the NTPD structure.
                   1250: 
                   1251:     // add the BYTE array to the end of the NTPD structure.
                   1252: 
                   1253:     pntpd->loFonts = pntpd->cjThis;
                   1254:     pntpd->cjThis += pntpd->cFonts;
                   1255: 
                   1256: #if SIZE_TEST
                   1257:     DbgPrint("post cFonts: cjThis = %d.\n", pntpd->cjThis);
                   1258: #endif
                   1259: 
                   1260:     pfont = (BYTE *)pntpd + pntpd->loFonts;
                   1261: 
                   1262:     for (i = 0; i < (DWORD)pntpd->cFonts; i++)
                   1263:     {
                   1264:         pfont[i] = ptmp->bFonts[i];
                   1265: #if TESTING
                   1266:        DbgPrint("Font[%d] = %d\n", i, (int)pfont[i]);
                   1267: #endif
                   1268:     }
                   1269: }
                   1270: 
                   1271: 
                   1272: //--------------------------------------------------------------------------
                   1273: // DWORD SizeNTPD(pntpd, ptmp)
                   1274: // PNTPD       pntpd;
                   1275: // PTMP_NTPD   ptmp;
                   1276: //
                   1277: // This routine determines the size of the NTPD structure for the
                   1278: // given printer.
                   1279: //
                   1280: // Returns:
                   1281: //   This routine returns the size of the NTPD structure in BYTES, or
                   1282: // zero for error.
                   1283: //
                   1284: // History:
                   1285: //   29-Sep-1992    -by-    Kent Settle     (kentse)
                   1286: //  Wrote it.
                   1287: //--------------------------------------------------------------------------
                   1288: 
                   1289: DWORD SizeNTPD(pntpd, ptmp)
                   1290: PNTPD       pntpd;
                   1291: PTMP_NTPD   ptmp;
                   1292: {
                   1293:     DWORD           i, dwSize;
                   1294: 
                   1295:     // start by adding the printer name to the end of the NTPD structure.
                   1296: 
                   1297: #if SIZE_TEST
                   1298:     DbgPrint("Entering SizeNTPD.\n");
                   1299: #endif
                   1300: 
                   1301:     dwSize = sizeof(NTPD);
                   1302:     dwSize = WCHARALIGN(dwSize);
                   1303:     dwSize += ptmp->cbPrinterName;
                   1304:     dwSize = DWORDALIGN(dwSize);
                   1305: 
                   1306: #if SIZE_TEST
                   1307:     DbgPrint("post cbPrinterName: dwSize = %d.\n", dwSize);
                   1308: #endif
                   1309: 
                   1310:     // now add the set resolution strings to the end of the structure,
                   1311:     // if there are any to add.  it is worth noting how these are stored
                   1312:     // in the NTPD structure.  an array of cResolutions PSRESOLUTION
                   1313:     // structures are stored at the end of the NTPD structure.  within
                   1314:     // each PSRESOLUTION structure is an offset to the string corresponding
                   1315:     // to the resolution in question.
                   1316: 
                   1317:     if (pntpd->cResolutions != 0)
                   1318:     {
                   1319:         // add the PSRESOLUTION array to the end of the NTPD structure.
                   1320: 
                   1321:         dwSize += pntpd->cResolutions * sizeof(PSRESOLUTION);
                   1322: 
                   1323:         // for each resolution, fill in the PSRESOLUTION structure.
                   1324:         // then add the string itself to the end of the NTPD structure.
                   1325: 
                   1326:         for (i = 0; i < (DWORD)pntpd->cResolutions; i++)
                   1327:             dwSize += (DWORD)szLength(ptmp->siResolutions[i].szString);
                   1328:     }
                   1329: 
                   1330: #if SIZE_TEST
                   1331:     DbgPrint("post resolutions: dwSize = %d.\n", dwSize);
                   1332: #endif
                   1333: 
                   1334:     // add the transfernormalized string to the end of the structure.
                   1335: 
                   1336:     dwSize += ptmp->cbTransferNorm;
                   1337: 
                   1338: #if SIZE_TEST
                   1339:     DbgPrint("post cbTransferNorm: dwSize = %d.\n", dwSize);
                   1340: #endif
                   1341: 
                   1342:     // add the inverse transfernormalized string to the end of the structure.
                   1343: 
                   1344:     dwSize += ptmp->cbInvTransferNorm;
                   1345: 
                   1346: #if SIZE_TEST
                   1347:     DbgPrint("post cbInvTransferNorm: dwSize = %d.\n", dwSize);
                   1348: #endif
                   1349: 
                   1350:     // add the form names list to the end of the structure.
                   1351: 
                   1352:     dwSize += szLength(ptmp->szDefaultForm);
                   1353:     dwSize = DWORDALIGN(dwSize);
                   1354: 
                   1355: #if SIZE_TEST
                   1356:     DbgPrint("post szDefaultForm: dwSize = %d.\n", dwSize);
                   1357: #endif
                   1358: 
                   1359:     dwSize += pntpd->cPSForms * sizeof(PSFORM);
                   1360: 
                   1361: #if SIZE_TEST
                   1362:     DbgPrint("post cPSForms: dwSize = %d.\n", dwSize);
                   1363: #endif
                   1364: 
                   1365:     // for each form, allow room for the FormName, SizeInvo, and
                   1366:     // RegionInvo strings.
                   1367: 
                   1368:     for (i = 0; i < pntpd->cPSForms; i++)
                   1369:     {
                   1370:         // account for the form name and invocation strings.
                   1371: 
                   1372:         dwSize += szLength(ptmp->FormEntry[i].szName) +
                   1373:                   szLength(ptmp->FormEntry[i].szInvocation);
                   1374: 
                   1375:     }
                   1376: 
                   1377: #if SIZE_TEST
                   1378:     DbgPrint("post all forms: dwSize = %d.\n", dwSize);
                   1379: #endif
                   1380: 
                   1381:     // make room for the page region invocation strings.
                   1382: 
                   1383:     for (i = 0; i < pntpd->cPageRegions; i++)
                   1384:         dwSize += szLength(ptmp->PageRegion[i].szInvocation);
                   1385: 
                   1386: #if SIZE_TEST
                   1387:     DbgPrint("post page regions: dwSize = %d.\n", dwSize);
                   1388: #endif
                   1389: 
                   1390:     // now add the outputbin strings to the end of the structure,
                   1391:     // if there are any to add.  it is worth noting how these are stored
                   1392:     // in the NTPD structure.  an array of cOutputBins PSOUTPUTBIN
                   1393:     // structures are stored at the end of the NTPD structure.  within
                   1394:     // each PSOUTPUTBIN structure are offsets to the strings corresponding
                   1395:     // to the output bin and invocation.  if there is only the default
                   1396:     // outputbin defined, cOutputBins will be zero.  otherwise it is assumed
                   1397:     // there will be at least two output bins defined.  if there is only one
                   1398:     // defined, it will be the same as the default.
                   1399: 
                   1400:     dwSize += szLength(ptmp->szDefaultOutputBin);
                   1401:     dwSize = DWORDALIGN(dwSize);
                   1402: 
                   1403: #if SIZE_TEST
                   1404:     DbgPrint("post szDefaultOutputBin: dwSize = %d.\n", dwSize);
                   1405: #endif
                   1406: 
                   1407:     if (pntpd->cOutputBins > 0)
                   1408:     {
                   1409:         dwSize += pntpd->cOutputBins * sizeof(PSOUTPUTBIN);
                   1410: 
                   1411:         // for each outputbin, fill in the PSOUTPUTBIN structure.
                   1412: 
                   1413:         for (i = 0; i < pntpd->cOutputBins; i++)
                   1414:         {
                   1415:             dwSize += szLength(ptmp->siOutputBin[i].szName);
                   1416:             dwSize += szLength(ptmp->siOutputBin[i].szInvocation);
                   1417:         }
                   1418:     }
                   1419: 
                   1420: #if SIZE_TEST
                   1421:     DbgPrint("post all output bins: dwSize = %d.\n", dwSize);
                   1422: #endif
                   1423: 
                   1424:     // now add the inputslot strings to the end of the structure,
                   1425:     // if there are any to add.  it is worth noting how these are stored
                   1426:     // in the NTPD structure.  an array of cInputSlots PSINPUTSLOT
                   1427:     // structures are stored at the end of the NTPD structure.  within
                   1428:     // each PSINPUTSLOT structure are offsets to the strings corresponding
                   1429:     // to the slot name and the invocation string.  if there is only the
                   1430:     // default inputslot defined, cInputSlots will be zero.  otherwise it
                   1431:     // is assumed there will be at least two input slots defined.  if there
                   1432:     // is only one defined, it will be the same as the default.
                   1433: 
                   1434:     dwSize += szLength(ptmp->szDefaultInputSlot);
                   1435:     dwSize = DWORDALIGN(dwSize);
                   1436: 
                   1437: #if SIZE_TEST
                   1438:     DbgPrint("post szDefaultInputSlot: dwSize = %d.\n", dwSize);
                   1439: #endif
                   1440: 
                   1441:     if (pntpd->cInputSlots > 0)
                   1442:     {
                   1443:         dwSize += pntpd->cInputSlots * sizeof(PSINPUTSLOT);
                   1444: 
                   1445:         // for each inputslot, fill in the PSINPUTSLOT structure.
                   1446: 
                   1447:         for (i = 0; i < pntpd->cInputSlots; i++)
                   1448:         {
                   1449:             dwSize += szLength(ptmp->siInputSlot[i].szName);
                   1450:             dwSize += szLength(ptmp->siInputSlot[i].szInvocation);
                   1451:         }
                   1452:     }
                   1453: 
                   1454: #if SIZE_TEST
                   1455:     DbgPrint("post all input slots: dwSize = %d.\n", dwSize);
                   1456: #endif
                   1457: 
                   1458:     // add the manualfeed strings to the end of the structure.
                   1459: 
                   1460:     dwSize += ptmp->cbManualTRUE + ptmp->cbManualFALSE;
                   1461: 
                   1462: #if SIZE_TEST
                   1463:     DbgPrint("post manual strings: dwSize = %d.\n", dwSize);
                   1464: #endif
                   1465: 
                   1466:     // add the duplex strings.
                   1467: 
                   1468:     dwSize += ptmp->cbDuplexNone + ptmp->cbDuplexTumble +
                   1469:               ptmp->cbDuplexNoTumble;
                   1470: 
                   1471: #if SIZE_TEST
                   1472:     DbgPrint("post duplex strings: dwSize = %d.\n", dwSize);
                   1473: #endif
                   1474: 
                   1475:     // add the collate strings.
                   1476: 
                   1477:     dwSize += ptmp->cbCollateOn + ptmp->cbCollateOff;
                   1478: 
                   1479: #if SIZE_TEST
                   1480:     DbgPrint("post collate strings: dwSize = %d.\n", dwSize);
                   1481: #endif
                   1482: 
                   1483:     // now add the fonts to the end of the structure,
                   1484:     // it is worth noting how these are stored in the NTPD structure.
                   1485:     // an array of pntpd->cFonts BYTES are stored at the end of the NTPD
                   1486:     // structure.
                   1487: 
                   1488:     // add the BYTE array to the end of the NTPD structure.
                   1489: 
                   1490:     dwSize += pntpd->cFonts;
                   1491: 
                   1492: #if SIZE_TEST
                   1493: DbgPrint("SizeNTPD - dwSize = %d.\n", dwSize);
                   1494: #endif
                   1495: 
                   1496:     return(dwSize);
                   1497: }
                   1498: 
                   1499: 
                   1500: //--------------------------------------------------------------------------
                   1501: //
                   1502: // BOOL GetBuffer();
                   1503: //
                   1504: // This routines reads a new buffer full of text from the input file.
                   1505: //
                   1506: // Note: If the end of file is encountered in this function then
                   1507: //     the program is aborted with an error message.    Normally
                   1508: //     the program will stop processing the input when it sees
                   1509: //     the end of information keyword.
                   1510: //
                   1511: // Parameters:
                   1512: //   None.
                   1513: //
                   1514: // Returns:
                   1515: //   This routine returns TRUE if end of file, FALSE otherwise.
                   1516: //
                   1517: // History:
                   1518: //   18-Mar-1991    -by-    Kent Settle    (kentse)
                   1519: //  Brought in from Windows 3.0, and cleaned up.
                   1520: //--------------------------------------------------------------------------
                   1521: 
                   1522: BOOL GetBuffer(pdata)
                   1523: PPARSEDATA  pdata;
                   1524: {
                   1525:     // initialize the buffer count to zero.
                   1526: 
                   1527:     pdata->cbBuffer = 0;
                   1528: 
                   1529:     // read in the next buffer full of data if we have not already hit the
                   1530:     // end of file.
                   1531: 
                   1532:     if (!pdata->fEOF)
                   1533:     {
                   1534:         ReadFile(pdata->hFile, pdata->rgbBuffer, sizeof(pdata->rgbBuffer),
                   1535:                  (LPDWORD)&pdata->cbBuffer, (LPOVERLAPPED)NULL);
                   1536: 
                   1537:         if (pdata->cbBuffer == 0)
                   1538:             pdata->fEOF = TRUE;
                   1539:     }
                   1540: 
                   1541:     pdata->pbBuffer = pdata->rgbBuffer;
                   1542:     return(pdata->fEOF);
                   1543: }
                   1544: 
                   1545: 
                   1546: //--------------------------------------------------------------------------
                   1547: //
                   1548: // BOOL GetLine(pdata);
                   1549: // PPARSEDATA   pdata;
                   1550: //
                   1551: // This routine gets the next line of text out of the input buffer.
                   1552: //
                   1553: // Parameters:
                   1554: //   None.
                   1555: //
                   1556: // Returns:
                   1557: //   This routine returns TRUE if end of file, FALSE otherwise.
                   1558: //
                   1559: // History:
                   1560: //   18-Mar-1991    -by-    Kent Settle    (kentse)
                   1561: //  Brought in from Windows 3.0, and cleaned up.
                   1562: //--------------------------------------------------------------------------
                   1563: 
                   1564: BOOL GetLine(pdata)
                   1565: PPARSEDATA  pdata;
                   1566: {
                   1567:     int cbLine;
                   1568:     char bCh;
                   1569: 
                   1570:     if (pdata->fUnGetLine)
                   1571:     {
                   1572:         pdata->szLine = pdata->rgbLine;
                   1573:         pdata->fUnGetLine = FALSE;
                   1574:         return(FALSE);
                   1575:     }
                   1576: 
                   1577:     cbLine = 0;
                   1578:     pdata->szLine = pdata->rgbLine;
                   1579:     *(pdata->szLine) = 0;
                   1580: 
                   1581:     if (!pdata->fEOF)
                   1582:     {
                   1583:         while(TRUE)
                   1584:         {
                   1585:             if (pdata->cbBuffer <= 0)
                   1586:             {
                   1587:                 if (GetBuffer(pdata))    // done if end of file hit.
                   1588:                 break;
                   1589:             }
                   1590: 
                   1591:             while(--pdata->cbBuffer >= 0)
                   1592:             {
                   1593:                 bCh = *(pdata->pbBuffer++);
                   1594:                 if (bCh == '\n' || bCh == '\r' || ++cbLine > sizeof(pdata->rgbLine))
                   1595:                 {
                   1596:                     *(pdata->szLine) = 0;
                   1597:                     pdata->szLine = pdata->rgbLine;
                   1598:                     EatWhite(pdata);
                   1599:                     if (*(pdata->szLine) != 0)
                   1600:                     {
                   1601:                         pdata->szLine = pdata->rgbLine;
                   1602:                         return(pdata->fEOF);
                   1603:                     }
                   1604: 
                   1605:                     pdata->szLine = pdata->rgbLine;
                   1606:                     cbLine = 0;
                   1607:                     continue;
                   1608:                 }
                   1609: 
                   1610:                 *(pdata->szLine++) = bCh;
                   1611:             }
                   1612:         }
                   1613:     }
                   1614: 
                   1615:     *(pdata->szLine) = 0;
                   1616: 
                   1617:     pdata->szLine = pdata->rgbLine;
                   1618:     return(pdata->fEOF);
                   1619: }
                   1620: 
                   1621: 
                   1622: //--------------------------------------------------------------------------
                   1623: //
                   1624: 
                   1625: // VOID UnGetLine(pdata)
                   1626: // PPARSEDATA  pdata;
                   1627: //
                   1628: // This routine pushes the most recent line back into the input buffer.
                   1629: //
                   1630: // Parameters:
                   1631: //   None.
                   1632: //
                   1633: // Returns:
                   1634: //   This routine returns no value.
                   1635: //
                   1636: // History:
                   1637: //   18-Mar-1991    -by-    Kent Settle    (kentse)
                   1638: //  Brought in from Windows 3.0, and cleaned up.
                   1639: //--------------------------------------------------------------------------
                   1640: 
                   1641: VOID UnGetLine(pdata)
                   1642: PPARSEDATA  pdata;
                   1643: {
                   1644:     pdata->fUnGetLine = TRUE;
                   1645:     pdata->szLine = pdata->rgbLine;
                   1646: }
                   1647: 
                   1648: 
                   1649: //--------------------------------------------------------------------------
                   1650: //
                   1651: // int GetKeyword(pTable, pdata)
                   1652: // TABLE_ENTRY    *pTable;
                   1653: // PPARSEDATA      pdata;
                   1654: //
                   1655: // Get the next token from the input stream.
                   1656: //
                   1657: // Parameters:
                   1658: //   None.
                   1659: //
                   1660: // Returns:
                   1661: //   This routine returns integer value of next token.
                   1662: //
                   1663: // History:
                   1664: //   18-Mar-1991    -by-    Kent Settle    (kentse)
                   1665: //  Brought in from Windows 3.0, and cleaned up.
                   1666: //--------------------------------------------------------------------------
                   1667: 
                   1668: int GetKeyword(pTable, pdata)
                   1669: TABLE_ENTRY    *pTable;
                   1670: PPARSEDATA      pdata;
                   1671: {
                   1672:     char szWord[256];
                   1673: 
                   1674:     if (*(pdata->szLine) == 0)
                   1675:         if (GetLine(pdata))
                   1676:             return(TK_EOF);
                   1677: 
                   1678:     GetWord(szWord, sizeof(szWord), pdata);
                   1679:     return(MapToken(szWord, pTable));
                   1680: }
                   1681: 
                   1682: 
                   1683: //--------------------------------------------------------------------------
                   1684: // VOID GetOptionString(pstrOptionName, cbBuffer, pdata)
                   1685: // PSTR        pstrOptionName;
                   1686: // DWORD       cbBuffer;
                   1687: // PPARSEDATA  pdata;
                   1688: //
                   1689: // This routine fills in the option name of the next option.
                   1690: //
                   1691: // Parameters:
                   1692: //   pstrOptionName - place to put option name.
                   1693: //
                   1694: //   cbBuffer - size of buffer.
                   1695: //
                   1696: // Returns:
                   1697: //   This routine returns no value.
                   1698: //
                   1699: // History:
                   1700: //   08-Apr-1992    -by-    Kent Settle     (kentse)
                   1701: //  Wrote it.
                   1702: //--------------------------------------------------------------------------
                   1703: 
                   1704: VOID GetOptionString(pstrOptionName, cbBuffer, pdata)
                   1705: PSTR        pstrOptionName;
                   1706: DWORD       cbBuffer;
                   1707: PPARSEDATA  pdata;
                   1708: {
                   1709:     if (*(pdata->szLine) == 0)
                   1710:         if (GetLine(pdata))
                   1711:             return;
                   1712: 
                   1713:     EatWhite(pdata);
                   1714: 
                   1715:     // copy the form name until the ':' deliminator is encountered.
                   1716: 
                   1717:     while (cbBuffer--)
                   1718:     {
                   1719:         *pstrOptionName = *(pdata->szLine++);
                   1720: 
                   1721:         if ((*pstrOptionName == ':') || (*pstrOptionName == '\0'))
                   1722:         {
                   1723:             *pstrOptionName = '\0';  // add the zero terminator.
                   1724:             break;
                   1725:         }
                   1726: 
                   1727:         pstrOptionName++;
                   1728:     }
                   1729: 
                   1730:     // strip off any trailing spaces, 'cause some people just can't
                   1731:     // follow the spec.
                   1732: 
                   1733:     pstrOptionName--;
                   1734: 
                   1735:     if ((*pstrOptionName == ' ') || (*pstrOptionName == '\t'))
                   1736:     {
                   1737:         while ((*pstrOptionName == ' ') || (*pstrOptionName == '\t'))
                   1738:             *pstrOptionName-- = '\0';
                   1739:     }
                   1740: 
                   1741:     return;
                   1742: }
                   1743: 
                   1744: 
                   1745: //--------------------------------------------------------------------------
                   1746: // int GetOptionIndex(pTable, pdata)
                   1747: // TABLE_ENTRY    *pTable;
                   1748: // PPARSEDATA      pdata;
                   1749: //
                   1750: // Get the next token from the input stream.
                   1751: //
                   1752: // Parameters:
                   1753: //   None.
                   1754: //
                   1755: // Returns:
                   1756: //   This routine returns integer value of next token.
                   1757: //
                   1758: // History:
                   1759: //   08-Apr-1991    -by-    Kent Settle     (kentse)
                   1760: //  Wrote it.
                   1761: //--------------------------------------------------------------------------
                   1762: 
                   1763: int GetOptionIndex(pTable, pdata)
                   1764: TABLE_ENTRY    *pTable;
                   1765: PPARSEDATA      pdata;
                   1766: {
                   1767:     char    szWord[256];
                   1768:     int     cbWord;
                   1769:     char   *pszWord;
                   1770: 
                   1771:     if (*(pdata->szLine) == 0)
                   1772:         if (GetLine(pdata))
                   1773:             return(TK_EOF);
                   1774: 
                   1775:     EatWhite(pdata);
                   1776: 
                   1777:     cbWord = sizeof(szWord);
                   1778:     pszWord = szWord;
                   1779: 
                   1780:     while (--cbWord > 0)
                   1781:     {
                   1782:         *pszWord = *(pdata->szLine++);
                   1783: 
                   1784:         // search to the end of the option.  this could be either the
                   1785:         // colon, which ends the option, or the slash, which begins the
                   1786:         // translation string (which we will ignore).
                   1787: 
                   1788:         if ((*pszWord == ':') || (*pszWord == '/'))
                   1789:         {
                   1790:             *pszWord = 0;
                   1791:             break;
                   1792:         }
                   1793: 
                   1794:         pszWord++;
                   1795:     }
                   1796: 
                   1797:     return(MapToken(szWord, pTable));
                   1798: }
                   1799: 
                   1800: 
                   1801: //--------------------------------------------------------------------------
                   1802: //
                   1803: // int MapToken(szWord, pTable)
                   1804: // char           *szWord;        // Ptr to the ascii keyword string
                   1805: // TABLE_ENTRY    *pTable;
                   1806: //
                   1807: // This routine maps an ascii key word into an integer token.
                   1808: //
                   1809: // Parameters:
                   1810: //   szWord
                   1811: //     Pointer to the ascii keyword string.
                   1812: //
                   1813: // Returns:
                   1814: //   This routine returns int identifying token.
                   1815: //
                   1816: // History:
                   1817: //   03-Apr-1991    -by-    Kent Settle    (kentse)
                   1818: //  Wrote it.
                   1819: //--------------------------------------------------------------------------
                   1820: 
                   1821: int MapToken(szWord, pTable)
                   1822: char           *szWord;        // Ptr to the ascii keyword string
                   1823: TABLE_ENTRY    *pTable;
                   1824: {
                   1825:     while (pTable->szStr)
                   1826:     {
                   1827:         if (szIsEqual(szWord, pTable->szStr))
                   1828:             return(pTable->iValue);
                   1829: 
                   1830:         ++pTable;
                   1831:     }
                   1832: 
                   1833: #if TESTING
                   1834:     DbgPrint("MapToken could not map %s.\n", szWord);
                   1835: #endif
                   1836:     return(TK_UNDEFINED);
                   1837: }
                   1838: 
                   1839: 
                   1840: //--------------------------------------------------------------------------
                   1841: // VOID GetWord(szWord, cbWord, pdata)
                   1842: // char       *szWord;        // Ptr to the destination area
                   1843: // int         cbWord;        // The size of the destination area
                   1844: // PPARSEDATA  pdata;
                   1845: //
                   1846: // This routine gets the next word delimited by white space
                   1847: // from the input buffer.
                   1848: //
                   1849: // Parameters:
                   1850: //   szWord
                   1851: //     Pointer to the destination area.
                   1852: //
                   1853: //   cbWord
                   1854: //     Size of destination area.
                   1855: //
                   1856: // Returns:
                   1857: //   This routine returns no value.
                   1858: //
                   1859: // History:
                   1860: //   18-Mar-1991    -by-    Kent Settle    (kentse)
                   1861: //  Brought in from Windows 3.0, and cleaned up.
                   1862: //--------------------------------------------------------------------------
                   1863: 
                   1864: VOID GetWord(szWord, cbWord, pdata)
                   1865: char       *szWord;        // Ptr to the destination area
                   1866: int         cbWord;        // The size of the destination area
                   1867: PPARSEDATA  pdata;
                   1868: {
                   1869:     char bCh;
                   1870: 
                   1871:     EatWhite(pdata);
                   1872:     while (cbWord--)
                   1873:     {
                   1874:         switch(bCh = *(pdata->szLine++))
                   1875:         {
                   1876:             case 0:
                   1877:             case ' ':
                   1878:             case '\t':
                   1879:             case '\n':     // take care of newline and carriage returns.
                   1880:             case '\r':
                   1881:                 --pdata->szLine;
                   1882:                 *szWord = 0;
                   1883:                 return;
                   1884:             case ':':       // the colon is a delimeter in PPD files,
                   1885:                 break;      // and should simply be skipped over.
                   1886:             default:
                   1887:                 *szWord++ = bCh;
                   1888:                 break;
                   1889:         }
                   1890:     }
                   1891: 
                   1892:     *szWord = 0;
                   1893: }
                   1894: 
                   1895: 
                   1896: //--------------------------------------------------------------------------
                   1897: // int GetString(szDst, pdata)
                   1898: // char       *szDst;
                   1899: // PPARSEDATA  pdata;
                   1900: //
                   1901: // This routine gets a " bracketed string from the ppd_file, attaching
                   1902: // a zero terminator to it.
                   1903: //
                   1904: // Returns:
                   1905: //   This routine returns the length of the string, including the zero
                   1906: //   terminator.
                   1907: //
                   1908: // History:
                   1909: //   03-Apr-1991    -by-    Kent Settle    (kentse)
                   1910: //  Wrote it.
                   1911: //--------------------------------------------------------------------------
                   1912: 
                   1913: int GetString(szDst, pdata)
                   1914: char       *szDst;
                   1915: PPARSEDATA  pdata;
                   1916: {
                   1917:     int     i;
                   1918: 
                   1919:     // advance to the first quotation mark, then one character past it.
                   1920: 
                   1921:     while (*(pdata->szLine) != '"')
                   1922:         pdata->szLine++;
                   1923:     pdata->szLine++;
                   1924: 
                   1925:     // initialize string length counter to include zero terminator.
                   1926: 
                   1927:     i = 1;
                   1928: 
                   1929:     // copy the string itself.  be sure to ignore ppd file comments (#).
                   1930: 
                   1931:     while (*(pdata->szLine) && *(pdata->szLine) != '"' &&
                   1932:            *(pdata->szLine) != '%')
                   1933:     {
                   1934:         *szDst++ = *(pdata->szLine++);
                   1935:         i++;
                   1936:     }
                   1937: 
                   1938:     // get the next line if the string is longer than one line.
                   1939: 
                   1940:     if (*(pdata->szLine) != '"')
                   1941:     {
                   1942:         while (!(GetLine(pdata)))
                   1943:         {
                   1944:             while (*(pdata->szLine) && *(pdata->szLine) != '"' &&
                   1945:                    *(pdata->szLine) != '%')
                   1946:             {
                   1947:                 *szDst++ = *(pdata->szLine++);
                   1948:                 i++;
                   1949:             }
                   1950: 
                   1951:             if (*(pdata->szLine) == '"')
                   1952:                 break;
                   1953: 
                   1954:             // how 'bout a new line.
                   1955: 
                   1956:             *szDst++ = '\n';
                   1957:             i++;
                   1958:         }
                   1959:     }
                   1960: 
                   1961:     // add the zero terminator.
                   1962: 
                   1963:     *szDst = 0;
                   1964: 
                   1965:     // return the length of the string.
                   1966: 
                   1967:     return (i);
                   1968: }
                   1969: 
                   1970: 
                   1971: //--------------------------------------------------------------------------
                   1972: // VOID EatWhite(pdata)
                   1973: // PPARSEDATA  pdata;
                   1974: //
                   1975: // This routine moves the input buffer pointer forward to the
                   1976: // next non-white character.
                   1977: //
                   1978: // Parameters:
                   1979: //   None.
                   1980: //
                   1981: // Returns:
                   1982: //   This routine returns TRUE if end of file, FALSE otherwise.
                   1983: //
                   1984: // History:
                   1985: //   18-Mar-1991    -by-    Kent Settle    (kentse)
                   1986: //  Brought in from Windows 3.0, and cleaned up.
                   1987: //--------------------------------------------------------------------------
                   1988: 
                   1989: VOID EatWhite(pdata)
                   1990: PPARSEDATA  pdata;
                   1991: {
                   1992:     while (TRUE)
                   1993:     {
                   1994:         // skip to the next line if necessary.
                   1995: 
                   1996:         if ((*(pdata->szLine) == '\0') || (*(pdata->szLine) == '\n') ||
                   1997:             (*(pdata->szLine) == '\r'))
                   1998:             GetLine(pdata);
                   1999: 
                   2000:         // we are done if we hit a non-white character.
                   2001: 
                   2002:         if ((*(pdata->szLine) != ' ') && (*(pdata->szLine) != '\t'))
                   2003:             break;
                   2004: 
                   2005:         pdata->szLine++;
                   2006:     }
                   2007: }
                   2008: 
                   2009: 
                   2010: //--------------------------------------------------------------------------
                   2011: // int GetNumber(pdata)
                   2012: // PPARSEDATA  pdata;
                   2013: //
                   2014: // This routine parses an ASCII decimal number from the
                   2015: // input file stream and returns its value.
                   2016: //
                   2017: // Parameters:
                   2018: //   None.
                   2019: //
                   2020: // Returns:
                   2021: //   This routine returns integer value of ASCII decimal number.
                   2022: //
                   2023: // History:
                   2024: //   18-Mar-1991    -by-    Kent Settle    (kentse)
                   2025: //  Brought in from Windows 3.0, and cleaned up.
                   2026: //--------------------------------------------------------------------------
                   2027: 
                   2028: int GetNumber(pdata)
                   2029: PPARSEDATA  pdata;
                   2030: {
                   2031:     int iVal;
                   2032:     BOOL fNegative;
                   2033: 
                   2034:     fNegative = FALSE;
                   2035: 
                   2036:     iVal = 0;
                   2037: 
                   2038:     EatWhite(pdata);
                   2039: 
                   2040:     // skip quotation mark if number is in quotes.
                   2041: 
                   2042:     if (*(pdata->szLine) == '"')
                   2043:     {
                   2044:         pdata->szLine++;
                   2045:         EatWhite(pdata);    // necessary if " 0 1".
                   2046:     }
                   2047: 
                   2048:     if (*(pdata->szLine) == '-')
                   2049:     {
                   2050:         fNegative = TRUE;
                   2051:         ++(pdata->szLine);
                   2052:     }
                   2053: 
                   2054:     // handle the case where the value is '.2'.  make it zero.
                   2055: 
                   2056:     if (*(pdata->szLine) == '.')
                   2057:     {
                   2058:         // skip all the fractional digits.
                   2059: 
                   2060:         while ((*(pdata->szLine)) && (*(pdata->szLine) != ' ') &&
                   2061:                (*(pdata->szLine) != '\t') && (*(pdata->szLine) != '"'))
                   2062:             pdata->szLine++;
                   2063: 
                   2064:         return(0);
                   2065:     }
                   2066: 
                   2067:     if (*(pdata->szLine) < '0' || *(pdata->szLine) > '9')
                   2068:     {
                   2069:         RIP("PSCRIPT!GetNumber:  invalid number found.  things will go bad from here.\n");
                   2070:         return(0);
                   2071:     }
                   2072: 
                   2073:     while (*(pdata->szLine) >= '0' && *(pdata->szLine) <= '9')
                   2074:         iVal = iVal * 10 + (*(pdata->szLine++) - '0');
                   2075: 
                   2076:     // some .PPD files, which will not be mentioned do NOT follow
                   2077:     // the Adobe spec, and put non-integer values where they
                   2078:     // do not belong.  therefore, if we hit a non-integer value,
                   2079:     // simply lop off the fraction.
                   2080: 
                   2081:     if (*(pdata->szLine) == '.')
                   2082:     {
                   2083:        // just skip along until we hit some white space.
                   2084: 
                   2085:         while ((*(pdata->szLine)) && (*(pdata->szLine) != ' ') &&
                   2086:                (*(pdata->szLine) != '\t') && (*(pdata->szLine) != '"'))
                   2087:            pdata->szLine++;
                   2088:     }
                   2089: 
                   2090:     if (fNegative)
                   2091:         iVal = - iVal;
                   2092: 
                   2093:     return(iVal);
                   2094: }
                   2095: 
                   2096: 
                   2097: //--------------------------------------------------------------------------
                   2098: // int GetFloat(iScale, pdata)
                   2099: // int         iScale;        // The amount to scale the value by
                   2100: // PPARSEDATA  pdata;
                   2101: //
                   2102: // This routine parses an ASCII floating point decimal number from the
                   2103: // input file stream and returns its value scaled by a specified amount.
                   2104: //
                   2105: // Parameters:
                   2106: //   None.
                   2107: //
                   2108: // Returns:
                   2109: //   This routine returns integer value of ASCII decimal number.
                   2110: //
                   2111: // History:
                   2112: //   18-Mar-1991    -by-    Kent Settle    (kentse)
                   2113: //  Brought in from Windows 3.0, and cleaned up.
                   2114: //--------------------------------------------------------------------------
                   2115: 
                   2116: int GetFloat(iScale, pdata)
                   2117: int         iScale;        // The amount to scale the value by
                   2118: PPARSEDATA  pdata;
                   2119: {
                   2120:     long lVal;
                   2121:     long lDivisor;
                   2122:     BOOL fNegative;
                   2123: 
                   2124:     EatWhite(pdata);
                   2125: 
                   2126:     fNegative = FALSE;
                   2127:     lVal = 0L;
                   2128: 
                   2129:     if (*(pdata->szLine) == '-')
                   2130:     {
                   2131:         fNegative = TRUE;
                   2132:         pdata->szLine++;
                   2133:     }
                   2134: 
                   2135:     if (*(pdata->szLine) < '0' || *(pdata->szLine) > '9')
                   2136:     {
                   2137:         RIP("PSCRIPT!GetFloat: invalid number.\n");
                   2138:         return(0);
                   2139:     }
                   2140: 
                   2141:     while (*(pdata->szLine) >= '0' && *(pdata->szLine) <= '9')
                   2142:         lVal = lVal * 10 + (*(pdata->szLine++) - '0');
                   2143: 
                   2144:     lDivisor = 1L;
                   2145:     if (*(pdata->szLine) == '.')
                   2146:     {
                   2147:         pdata->szLine++;
                   2148:         while (*(pdata->szLine) >= '0' && *(pdata->szLine) <= '9')
                   2149:         {
                   2150:             lVal = lVal * 10 + (*(pdata->szLine++) - '0');
                   2151:             lDivisor = lDivisor * 10;
                   2152:         }
                   2153:     }
                   2154:     lVal = (lVal * iScale) / lDivisor;
                   2155: 
                   2156:     if (fNegative)
                   2157:         lVal = - lVal;
                   2158: 
                   2159:     return((short)lVal);
                   2160: }
                   2161: 
                   2162: 
                   2163: //--------------------------------------------------------------------------
                   2164: // void GetDimension(pdim, pdata)
                   2165: // PAPERDIM   *pdim;
                   2166: // PPARSEDATA  pdata;
                   2167: //
                   2168: // This routine extracts the paper dimension from the ppd file.
                   2169: //
                   2170: // Returns:
                   2171: //   This routine returns no value.
                   2172: //
                   2173: // History:
                   2174: //   03-Apr-1991    -by-    Kent Settle     (kentse)
                   2175: //  Rewrote it.
                   2176: //   25-Mar-1991    -by-    Kent Settle    (kentse)
                   2177: //  Stole from Windows 3.0, and cleaned up.
                   2178: //--------------------------------------------------------------------------
                   2179: 
                   2180: void GetDimension(pdim, pdata)
                   2181: PAPERDIM   *pdim;
                   2182: PPARSEDATA  pdata;
                   2183: {
                   2184:     pdim->sizl.cx = GetNumber(pdata);
                   2185:     EatWhite(pdata);
                   2186:     pdim->sizl.cy = GetNumber(pdata);
                   2187: }
                   2188: 
                   2189: 
                   2190: //--------------------------------------------------------------------------
                   2191: // void GetImageableArea(prect, pdata)
                   2192: // RECTL      *prect;
                   2193: // PPARSEDATA  pdata;
                   2194: //
                   2195: // This routine extracts the imageable area from the ppd file.
                   2196: //
                   2197: // Returns:
                   2198: //   This routine returns no value.
                   2199: //
                   2200: // History:
                   2201: //   03-Apr-1991    -by-    Kent Settle     (kentse)
                   2202: //  Rewrote it.
                   2203: //   25-Mar-1991    -by-    Kent Settle    (kentse)
                   2204: //  Stole from Windows 3.0, and cleaned up.
                   2205: //--------------------------------------------------------------------------
                   2206: 
                   2207: void GetImageableArea(prect, pdata)
                   2208: RECTL      *prect;
                   2209: PPARSEDATA  pdata;
                   2210: {
                   2211:     prect->left = GetNumber(pdata);
                   2212:     prect->bottom = GetNumber(pdata);
                   2213:     prect->right = GetNumber(pdata);
                   2214:     prect->top = GetNumber(pdata);
                   2215: }
                   2216: 
                   2217: 
                   2218: //--------------------------------------------------------------------
                   2219: // szLength(pszScan)
                   2220: //
                   2221: // This routine calculates the length of a given string, including
                   2222: // the terminating NULL.  This routine checks to make sure the
                   2223: // string is not longer than MAX_STRING.
                   2224: //
                   2225: // History:
                   2226: //   19-Mar-1991        -by-    Kent Settle     (kentse)
                   2227: // Created.
                   2228: //--------------------------------------------------------------------
                   2229: 
                   2230: int szLength(pszScan)
                   2231: char    *pszScan;
                   2232: {
                   2233:     int i;
                   2234:     char *pszTmp;
                   2235: 
                   2236:     pszTmp = pszScan;
                   2237: 
                   2238:     i = 1;
                   2239:     while (*pszScan++ != '\0')
                   2240:         i++;
                   2241: 
                   2242:     // do a little internal checking.
                   2243: 
                   2244:     if (i > MAX_PPD_STRING)
                   2245:     {
                   2246:        DbgPrint("String Length too long!\n");
                   2247:        DbgPrint("Offending String: \"%s\"", pszTmp);
                   2248:         RIP("PSCRIPT!szLength:  about to overrun buffer.\n");
                   2249:     }
                   2250: 
                   2251:     return(i);
                   2252: }
                   2253: 
                   2254: 
                   2255: //--------------------------------------------------------------------------
                   2256: //
                   2257: // BOOL szIsEqual(sz1, sz2)
                   2258: // char *sz1;
                   2259: // char *sz2;
                   2260: //
                   2261: // This routine compares two NULL terminated strings.
                   2262: //
                   2263: // Parameters:
                   2264: //   sz1
                   2265: //     Pointer to string 1.
                   2266: //
                   2267: //   sz2
                   2268: //     Pointer to string2.
                   2269: //
                   2270: // Returns:
                   2271: //   This routine returns TRUE if strings are same, FALSE otherwise.
                   2272: //
                   2273: // History:
                   2274: //   18-Mar-1991    -by-    Kent Settle    (kentse)
                   2275: //  Brought in from Windows 3.0, and cleaned up.
                   2276: //--------------------------------------------------------------------------
                   2277: 
                   2278: BOOL szIsEqual(sz1, sz2)
                   2279: char *sz1;
                   2280: char *sz2;
                   2281: {
                   2282:     while (*sz1 && *sz2)
                   2283:     {
                   2284:         if (*sz1++ != *sz2++)
                   2285:             return(FALSE);
                   2286:     }
                   2287: 
                   2288:     return(*sz1 == *sz2);
                   2289: }
                   2290: 
                   2291: 
                   2292: //--------------------------------------------------------------------------
                   2293: // int NameComp(pname1, pname2)
                   2294: // CHAR   *pname1;
                   2295: // CHAR   *pname2;
                   2296: //
                   2297: // This routine is a glorified version of strcmp, in that it first gets
                   2298: // rid of any PostScript translation strings before comparing the strings.
                   2299: //
                   2300: // Returns same as strcmp.
                   2301: //
                   2302: // History:
                   2303: //   20-Mar-1993    -by-    Kent Settle     (kentse)
                   2304: //  Wrote it.
                   2305: //--------------------------------------------------------------------------
                   2306: 
                   2307: int NameComp(pname1, pname2)
                   2308: CHAR   *pname1;
                   2309: CHAR   *pname2;
                   2310: {
                   2311:     CHAR    buf1[MAX_PS_NAME];
                   2312:     CHAR    buf2[MAX_PS_NAME];
                   2313:     PSTR    pstr1, pstr2;
                   2314: 
                   2315:     // loop through the first name.  copy it into a buffer until we hit
                   2316:     // either the NULL terminator, or the '/' translation string deliminator.
                   2317: 
                   2318:     pstr1 = pname1;
                   2319:     pstr2 = buf1;
                   2320: 
                   2321:     while (*pstr1 && (*pstr1 != '/'))
                   2322:         *pstr2++ = *pstr1++;
                   2323: 
                   2324:     *pstr2 = '\0';
                   2325: 
                   2326:     // now do the same for the second name.
                   2327: 
                   2328:     pstr1 = pname2;
                   2329:     pstr2 = buf2;
                   2330: 
                   2331:     while (*pstr1 && (*pstr1 != '/'))
                   2332:         *pstr2++ = *pstr1++;
                   2333: 
                   2334:     *pstr2 = '\0';
                   2335: 
                   2336:     // now both buffers contain the names with any translation strings removed.
                   2337: 
                   2338:     return(strcmp(buf1, buf2));
                   2339: }
                   2340: 
                   2341: 
                   2342: //--------------------------------------------------------------------------
                   2343: // int NameComp(pname1, pname2)
                   2344: // CHAR   *pname1;
                   2345: // CHAR   *pname2;
                   2346: //
                   2347: // This routine is a glorified version of strcmp, in that it first gets
                   2348: // rid of any PostScript translation strings before comparing the strings.
                   2349: //
                   2350: // Returns same as strcmp.
                   2351: //
                   2352: // History:
                   2353: //   20-Mar-1993    -by-    Kent Settle     (kentse)
                   2354: //  Wrote it.
                   2355: //--------------------------------------------------------------------------
                   2356: 
                   2357: VOID ParseProtocols(pdata, pntpd)
                   2358: PPARSEDATA      pdata;
                   2359: PNTPD           pntpd;
                   2360: {
                   2361:     CHAR    buf[256];
                   2362:     CHAR   *pbuf;
                   2363:     BOOL    bMore, bWordDone;
                   2364:     CHAR    jCh;
                   2365:     DWORD   cjBuf;
                   2366: 
                   2367:     // there may be several protocols defined, so loop until we get
                   2368:     // them all.
                   2369: 
                   2370:     bMore = TRUE;
                   2371: 
                   2372:     while (bMore)
                   2373:     {
                   2374:         // gobble up any white space.
                   2375: 
                   2376:         EatWhite(pdata);
                   2377: 
                   2378:         pbuf = buf;
                   2379:         cjBuf = sizeof(buf) - 1;
                   2380: 
                   2381:         bWordDone = FALSE;
                   2382: 
                   2383:         while(cjBuf--)
                   2384:         {
                   2385:             switch(jCh = *(pdata->szLine++))
                   2386:             {
                   2387:                 case 0:
                   2388:                 case '\n':     // take care of newline and carriage returns.
                   2389:                 case '\r':
                   2390:                     --pdata->szLine;
                   2391:                     *pbuf = 0;
                   2392:                     bMore = FALSE;
                   2393:                     bWordDone = TRUE;
                   2394:                     break;
                   2395:                 case ' ':
                   2396:                 case '\t':
                   2397:                     --pdata->szLine;
                   2398:                     *pbuf = 0;
                   2399:                     bWordDone = TRUE;
                   2400:                     break;
                   2401:                 default:
                   2402:                     *pbuf++ = jCh;
                   2403:                     break;
                   2404:             }
                   2405: 
                   2406:             if (bWordDone)
                   2407:             {
                   2408:                 // reset pointer to start of buffer.
                   2409: 
                   2410:                 pbuf = buf;
                   2411:                 cjBuf = sizeof(buf) - 1;
                   2412: 
                   2413:                 if (!(strncmp(pbuf, "PJL", 3)))
                   2414:                 {
                   2415:                     pntpd->flFlags |= PJL_PROTOCOL;
                   2416: #if TESTING
                   2417:                     DbgPrint("Device supports PJL protocol.\n");
                   2418: #endif
                   2419:                 }
                   2420:                 else if (!(strncmp(pbuf, "SIC", 3)))
                   2421:                 {
                   2422:                     pntpd->flFlags |= SIC_PROTOCOL;
                   2423: #if TESTING
                   2424:                     DbgPrint("Device supports SIC protocol.\n");
                   2425: #endif
                   2426:                 }
                   2427: 
                   2428:                 // now go see if there is another protocol to parse.
                   2429: 
                   2430:                 break;
                   2431:             }
                   2432:         }
                   2433: 
                   2434:     }
                   2435: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.