home *** CD-ROM | disk | FTP | other *** search
/ Software Collection (I) / TOOLS.iso / b05 / 6.img / PSCRIPT / PROFILE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-11  |  49.2 KB  |  1,630 lines

  1. /**[f******************************************************************
  2.  * profile.c -
  3.  *
  4.  * Copyright (C) 1988 Aldus Corporation.  All rights reserved.
  5.  * Copyright (C) 1989 Microsoft Corporation.
  6.  * Company confidential.
  7.  *
  8.  **f]*****************************************************************/
  9.  
  10. /*********************************************************************
  11.  * PROFILE.C
  12.  *
  13.  * 14Aug87 sjp    Moved MapProfile(), GetPaperType() and ReadProfile()
  14.  *        from segment RESET.
  15.  *
  16.  * 88Jan13 chrisg    established MakeEnv and SaveEnv as means to
  17.  *            change load/save envs and got rid of global
  18.  *            devmode usage.
  19.  *
  20.  * 91Mar26 msd        Added support for Duplex.
  21.  *
  22.  * 91Jun12 peterwo  added new entry point DevInstall()
  23.  *
  24.  *********************************************************************/
  25.  
  26. #include "pscript.h"
  27. #include <winexp.h>
  28. #include "utils.h"
  29. #include "debug.h"
  30. #include "resource.h"
  31. #include "defaults.h"
  32. #include "psdata.h"
  33. #include "profile.h"
  34. #include "pserrors.h"
  35. #include "getdata.h"
  36. #include "dmrc.h"
  37. #include "psver.h"
  38. #include "control2.h"
  39. #include "enum.h"
  40. #include "etm.h"
  41. #include "truetype.h"
  42.  
  43. /* temporary until windows.h gets real */
  44. int  PASCAL GetInt( LPSTR, LPSTR, int, LPSTR );
  45. int  PASCAL GetString( LPSTR, LPSTR, LPSTR, LPSTR, int, LPSTR );
  46. BOOL PASCAL WriteString( LPSTR, LPSTR, LPSTR, LPSTR );
  47. int FAR PASCAL fnSubFilterProc(LPLOGFONT lplf, LPTEXTMETRIC lptm, short nType,
  48.                                DWORD dwData);
  49.  
  50.  
  51. /* these should go in win.h */
  52. int     FAR PASCAL GetPrivateProfileInt( LPSTR, LPSTR, int, LPSTR );
  53. int     FAR PASCAL GetPrivateProfileString( LPSTR, LPSTR, LPSTR, LPSTR, int, LPSTR );
  54. BOOL    FAR PASCAL WritePrivateProfileString( LPSTR, LPSTR, LPSTR, LPSTR );
  55.  
  56.  
  57. /*--------------------------- global data ------------------------*/
  58.  
  59. #define MAXSUBS 128     /* maximum number of font substitutions */
  60.  
  61. extern HWND ghwndDlg;
  62.  
  63. /* GetPrinter cache.  Remember last printer requested in a local discardable
  64. ** memory block.
  65. */
  66. extern HANDLE ghLastPrinter;
  67. extern int giLastPrinter;
  68.  
  69. void    FAR PASCAL InitDefaults(HWND hwnd, PPRINTER pPrinter);
  70.  
  71.  
  72. /*--------------------------- local functions ------------------------*/
  73.  
  74. int    PASCAL GetPaperType(LPSTR, int, LPSTR);
  75. void    PASCAL WriteProfileInt(LPSTR, LPSTR, int, LPSTR);
  76. void    PASCAL WriteProfile(LPSTR, LPPSDEVMODE, LPPSDEVMODE, LPSTR);
  77. void    PASCAL ReadProfile(LPSTR, LPPSDEVMODE, LPSTR, LPSTR);
  78.  
  79. int NEAR PASCAL MatchPrinterFromWPD(LPSTR lpName);
  80.  
  81. int FAR PASCAL SubTabProc(LPLOGFONT lplf, LPTEXTMETRIC lptm, short nType,
  82.                            LPSTR dwData);
  83.  
  84. /* use these until private profile gets fixed */
  85.  
  86. int PASCAL WriteString(LPSTR sec, LPSTR key, LPSTR buf, LPSTR pro )
  87. {
  88.     if (pro)
  89.         return WritePrivateProfileString(sec, key, buf, pro);
  90.     else
  91.         return WriteProfileString(sec, key, buf);
  92. }
  93.  
  94. int PASCAL GetString(LPSTR sec, LPSTR key, LPSTR def, LPSTR buf, int size, LPSTR pro )
  95. {
  96.     if (pro)
  97.         return GetPrivateProfileString(sec, key, def, buf, size, pro);
  98.     else
  99.         return GetProfileString(sec, key, def, buf, size);
  100. }
  101.  
  102.  
  103. int PASCAL GetInt(LPSTR sec, LPSTR key, int def, LPSTR pro )
  104. {
  105.     if (pro)
  106.         return GetPrivateProfileInt(sec, key, def, pro);
  107.     else
  108.         return GetProfileInt(sec, key, def);
  109. }
  110.  
  111.  
  112.  
  113. int FAR PASCAL MatchPrinter(LPSTR lpName)
  114. {
  115.     PPRINTER pPrinter;
  116.     char buf[40];
  117.     int i;
  118.     int num_ext;
  119.     char szModel[32];
  120.  
  121.     // (10/21/91 ZhanW) support custom printer names
  122.     if (GetProfileString("PrinterAliases", lpName, "", szModel, sizeof(szModel)))
  123.     lpName = (LPSTR)szModel;
  124.  
  125.         /* Check the GetPrinter cache first before searching ... */
  126.         if (giLastPrinter >= 0) {
  127.             pPrinter = (PPRINTER)LocalLock(ghLastPrinter);
  128.             if (pPrinter)
  129.                 i = lstrcmpi(pPrinter->Name, lpName);
  130.             LocalUnlock(ghLastPrinter);
  131.  
  132.             if (!i)
  133.                 return giLastPrinter;
  134.         }
  135.  
  136.     LoadString (ghInst, IDS_EXTPRINTERS, buf, sizeof(buf));
  137.     num_ext = GetProfileInt(szModule, buf, 0);
  138.  
  139.     for (i = INT_PRINTER_MIN; i <= (INT_PRINTER_MAX + num_ext); i++) {
  140.  
  141.         if (pPrinter = GetPrinter(i)) {
  142.  
  143.             if (!lstrcmpi(pPrinter->Name, lpName)) {
  144.                 FreePrinter(pPrinter);
  145.                 return i;
  146.             }
  147.  
  148.             FreePrinter(pPrinter);
  149.         }
  150.     }
  151.  
  152.         return MatchPrinterFromWPD(lpName);
  153. }
  154.  
  155. LONG FAR PASCAL QueryDeviceNames(HANDLE hDriver, LPSTR lpaDeviceName)
  156. {
  157.     PPRINTER pPrinter;
  158.     char buf[40];
  159.     int i;
  160.     int num_ext, num_printers;
  161.  
  162.     LoadString (ghInst, IDS_EXTPRINTERS, buf, sizeof(buf));
  163.     num_ext = GetProfileInt(szModule, buf, 0);
  164.  
  165.     num_printers = 0;
  166.     for (i = INT_PRINTER_MIN; i <= (INT_PRINTER_MAX + num_ext); i++) {
  167.  
  168.         if (pPrinter = GetPrinter(i)) {
  169.  
  170.                     ++num_printers;
  171.  
  172.                     if (lpaDeviceName) {
  173.                         lstrcpy(lpaDeviceName, pPrinter->Name);
  174.                         lpaDeviceName += 64;
  175.                     }
  176.  
  177.             FreePrinter(pPrinter);
  178.         }
  179.     }
  180.  
  181.     return num_printers;
  182. }
  183.  
  184. int FAR PASCAL OutputDebugString(LPSTR);
  185.  
  186. // do findfirst/findnext to get all the WPD files from the system
  187. // directory.  If wpd file already in external printer list skip it.
  188. // Otherwise load it in and see if the name matches.  If so, add it
  189. // to the external printer list, update the internal data structures,
  190. // and return its printer number.  If a matching driver isn't found
  191. // return 0.
  192. int NEAR PASCAL MatchPrinterFromWPD(LPSTR lpName)
  193. {
  194.     FCB fcb;
  195.     char szSpec[160], buf[20];
  196.     LPSTR lpTmp, lpszFilename;
  197.     int rc, fh, cb;
  198.     OFSTRUCT of;
  199.     PPRINTER pPrinter;
  200.     PS_RES_HEADER header;
  201.     int nExtPrinters, nNewPrinter;
  202.     BOOL  bFirstPass = TRUE;
  203.  
  204.     // build the search string
  205. SECOND_PASS:
  206.     if(bFirstPass)
  207.         GetSystemDirectory(szSpec, 160);
  208.     else
  209.         GetWindowsDirectory(szSpec, 160);
  210.  
  211.     lpszFilename = szSpec + lstrlen(szSpec);
  212.     lpszFilename = AnsiPrev(szSpec, lpszFilename);
  213.     if (*lpszFilename != '\\') {
  214.         lpszFilename = AnsiNext(lpszFilename);
  215.         *lpszFilename = '\\';
  216.     }
  217.     lpszFilename = AnsiNext(lpszFilename);
  218.     *lpszFilename = '\0';
  219.     lstrcat(szSpec, "*");
  220.     lstrcat(szSpec, szRes);
  221.  
  222.     // assume we can't find printer by using error code
  223.     nNewPrinter = -1;
  224.  
  225.     // process all of the WPD files in the SYSTEM directory...
  226.     for (rc = DosFindFirst(&fcb, szSpec, ATTR_ARCHIVE); !rc;
  227.          rc = DosFindNext(&fcb))
  228.     {
  229.  
  230.         // open the WPD file
  231.         lstrcpy(lpszFilename, fcb.szName);
  232.         fh = OpenFile(szSpec, &of, OF_READ);
  233.         if (fh == -1)
  234.             continue;
  235.  
  236.         if (_lread(fh, (LPSTR)&header, sizeof(header)) != sizeof(header))
  237.                 goto DONE_CLOSE;
  238.  
  239.         cb = header.cap_len;         // get the cap size
  240.         _llseek(fh, header.cap_loc, 0);    // position the file pointer
  241.  
  242.         if (!(pPrinter = (PPRINTER)LocalAlloc(LPTR, cb)))
  243.             goto DONE_CLOSE;
  244.  
  245.         cb = _lread(fh, (LPSTR)pPrinter, cb);
  246.  
  247.         if (!lstrcmpi(pPrinter->Name, lpName))
  248.         {
  249.             LoadString(ghInst, IDS_EXTPRINTERS, szSpec, sizeof(szSpec));
  250.  
  251.             nExtPrinters = GetProfileInt(szModule, szSpec, 0);
  252.  
  253.             nExtPrinters++;    /* adding a new printer */
  254.  
  255.             nNewPrinter = nExtPrinters + EXT_PRINTER_MIN - 1;
  256.  
  257.             wsprintf(buf, "%d", nExtPrinters);
  258.  
  259.             WriteProfileString(szModule, szSpec, buf);
  260.  
  261.             LoadString(ghInst, IDS_PRINTER, szSpec, sizeof(szSpec));
  262.  
  263.             wsprintf(buf, szSpec, nExtPrinters);
  264.  
  265.         // whack off extension
  266.             for (lpTmp = fcb.szName; *lpTmp && *lpTmp != '.';
  267.                 lpTmp = AnsiNext(lpTmp))
  268.                 ;
  269.             *lpTmp = '\0';
  270.  
  271.             WriteProfileString(szModule, buf, fcb.szName);
  272.  
  273. #ifdef APPLE_TALK
  274.             if (ghwndDlg)
  275.                 InitDefaults(ghwndDlg, pPrinter);
  276. #endif
  277.  
  278.             LocalFree((HANDLE)pPrinter);
  279.             _lclose(fh);
  280.  
  281.             return nNewPrinter;
  282.         }
  283.  
  284.         LocalFree((HANDLE)pPrinter);
  285.  
  286. DONE_CLOSE:
  287.         _lclose(fh);
  288.  
  289.     }
  290.  
  291.     if(bFirstPass)
  292.     {
  293.         bFirstPass = FALSE;
  294.         goto  SECOND_PASS ;
  295.     }
  296.  
  297.     return nNewPrinter;
  298. }
  299.  
  300.  
  301. /****************************************************************************
  302.  * void FAR PASCAL MakeEnvironment(lszDevType, lszFile, lpdm, lpProfile)
  303.  *
  304.  * fill the PSDEVMODE struct with a copy of the enviornment for *lszFile
  305.  * and *lszDevType.  Then init this struct with the values from win.ini
  306.  *
  307.  * in:
  308.  *    hinst        driver instance handle
  309.  *    lszDevType    device name "PostScript Printer" or
  310.  *            "IBM Personal PP II", etc.
  311.  *    lszFile        file or port name ("COM1:")
  312.  *    lpProfile    file to read to (win.ini if NULL)
  313.  *
  314.  * out:
  315.  *    lpdm    filled with initialized devmode struct
  316.  *
  317.  * returns:
  318.  *    TRUE        if new env read from win ini
  319.  *    FALSE        PSCRIPT env already existed
  320.  *
  321.  ****************************************************************************/
  322.  
  323. #define STR_EQ(s1, s2) (lstrcmpi((s1),(s2)) == 0)
  324.  
  325. BOOL FAR PASCAL MakeEnvironment(lszDevType, lszFile, lpdm, lpProfile)
  326. LPSTR    lszDevType;
  327. LPSTR    lszFile;
  328. LPPSDEVMODE lpdm;
  329. LPSTR    lpProfile;
  330. {
  331.     BOOL  result;
  332.     BYTE  buffer[80];
  333.  
  334.     if (STR_EQ("PostScript Printer", lszDevType))
  335.     {
  336.         LPSTR  lpDrvname;
  337.         int   i;
  338.         BOOL  bTwoCommas = FALSE;
  339.  
  340.         lpDrvname = buffer;  // initialize before we get in trouble
  341.         buffer[0] = '\0';
  342.  
  343.         GetProfileString("windows", "device", "", (LPSTR)buffer,
  344.             80);
  345.  
  346.         //  this for loop expects that buffer[] contains three strings
  347.         //  delimited by two commas.  It replaces both commas with NULLs
  348.         //  and sets lpDrvname to point to the second string.
  349.  
  350.         for(i = 0 ; buffer[i] ; i++)
  351.         {
  352.             if(buffer[i] == ',')
  353.             {
  354.                 buffer[i] = '\0';
  355.                 lpDrvname = buffer + ++i;
  356.                 for(  ; buffer[i] ; i++)
  357.                 {
  358.                     if(buffer[i] == ',')
  359.                     {
  360.                         buffer[i] = '\0';
  361.                         bTwoCommas = TRUE;
  362.                         break;
  363.                     }
  364.                 }
  365.                 break;
  366.             }
  367.         }
  368.         if(bTwoCommas  &&  lpDrvname != buffer  &&
  369.               STR_EQ(lpDrvname, "pscript")  &&
  370.               !STR_EQ((LPSTR)buffer, lszDevType) )
  371.             lszDevType = buffer;
  372.         else
  373.             lszDevType = "Apple LaserWriter Plus";
  374.  
  375.     }
  376.  
  377.     DBMSG(("\n>MakeEnv(%ls %ls %lp %ls)\n",
  378.         lszDevType, lszFile, lpdm, lpProfile));
  379.  
  380.     /* copy the module name into the first part of the env incase
  381.      * lszFile is the null port.  in this case GetEnv uses the first
  382.      * string (our module name) for the env search */
  383.  
  384.     lstrcpy(lpdm->dm.dmDeviceName, szModule);
  385.  
  386.     /* if (env doesn't exists || does exists and doesn't belong to us) */
  387.  
  388.     if ((GetEnvironment(lszFile, (LPSTR)lpdm, sizeof(PSDEVMODE)) == 0) ||
  389.         (lstrcmpi(lszDevType, lpdm->dm.dmDeviceName) != 0))
  390.     {
  391.              /* read env from win.ini */
  392.         DBMSG(("\n MakeEnv read win.ini\n"));
  393.  
  394.         ReadProfile(lszFile, lpdm, lszDevType, lpProfile);
  395.  
  396.         result = TRUE;        /* was created */
  397.  
  398.     } else
  399.  
  400.         result = FALSE;        /* already existed */
  401.  
  402.     lpdm->dm.dmSize = sizeof(DEVMODE);
  403.     lpdm->dm.dmSpecVersion = GDI_VERSION;
  404.     lpdm->dm.dmDriverVersion = DRIVER_VERSION;
  405.     lpdm->dm.dmDriverExtra = sizeof(PSDEVMODE) - sizeof(DEVMODE);
  406.  
  407.     lpdm->dm.dmFields = DM_ORIENTATION    |
  408.                 DM_PAPERSIZE    |
  409.                 DM_PAPERLENGTH    |
  410.                 DM_PAPERWIDTH    |
  411.                 DM_SCALE        |
  412.                 DM_COPIES        |
  413.                 DM_DEFAULTSOURCE    |
  414.                 DM_COLOR            |
  415.                             DM_DUPLEX;
  416.  
  417.  
  418.     if(lpdm->bSubFonts == TRUE)
  419.         lpdm->dm.dmTTOption = DMTT_SUBDEV;
  420.     else
  421.         lpdm->dm.dmTTOption = DMTT_DOWNLOAD;
  422.  
  423.     lpdm->dm.dmFields |= DM_TTOPTION;
  424.  
  425.     DBMSG(("\n<MakeEnv() lszFile:%ls\n", lszFile));
  426.     return result;
  427. }
  428.  
  429.  
  430. /****************************************************************************
  431.  * void FAR PASCAL SaveEnvironment(lszDevType, lszFile, lpdm,
  432.  *                   lpOrigDM, lpProfilefWriteProfile, fSendMsg)
  433.  *
  434.  * save the enviornemnt for lszDevType and lszFile defined by lpdm.
  435.  * the new enviornemnt is saved for the current session by GDI with
  436.  * SetEnviornment and optionally saved to win.ini.
  437.  *
  438.  * in:
  439.  *    hinst        driver instance handle
  440.  *    lszDevType    device type ("PostScript Printer")
  441.  *    lszFile        file or port name ("COM1:")
  442.  *    lpdm        enviornment to save
  443.  *    lpProfile    profile to write to
  444.  *    lpOrigDM    original devmode used to minimize writing to win.ini
  445.  *            this may be NULL if fWriteProfile is FALSE
  446.  *    fWriteProfile    write the new env to win.ini or not
  447.  *    fSendMsg    set a message to all apps indicating devmode change
  448.  *
  449.  ****************************************************************************/
  450.  
  451. void FAR PASCAL SaveEnvironment(lszDevType, lszFile, lpdm, lpOrigDM,
  452.                 lpProfile, fWriteProfile, fSendMsg)
  453. LPSTR        lszDevType;
  454. LPSTR        lszFile;
  455. LPPSDEVMODE    lpdm;
  456. LPPSDEVMODE    lpOrigDM;
  457. LPSTR        lpProfile;
  458. BOOL        fWriteProfile;    /* TRUE write profile to win.ini */
  459. BOOL        fSendMsg;    /* TRUE send message to all windows */
  460. {
  461.     BYTE  buffer[80];
  462.  
  463.     if (STR_EQ("PostScript Printer", lszDevType))
  464.     {
  465.         LPSTR  lpDrvname;
  466.         int   i;
  467.         BOOL  bTwoCommas = FALSE;
  468.  
  469.         lpDrvname = buffer;  // initialize before we get in trouble
  470.         buffer[0] = '\0';
  471.  
  472.         GetProfileString("windows", "device", "", (LPSTR)buffer,
  473.             80);
  474.  
  475.         //  this for loop expects that buffer[] contains three strings
  476.         //  delimited by two commas.  It replaces both commas with NULLs
  477.         //  and sets lpDrvname to point to the second string.
  478.  
  479.         for(i = 0 ; buffer[i] ; i++)
  480.         {
  481.             if(buffer[i] == ',')
  482.             {
  483.                 buffer[i] = '\0';
  484.                 lpDrvname = buffer + ++i;
  485.                 for(  ; buffer[i] ; i++)
  486.                 {
  487.                     if(buffer[i] == ',')
  488.                     {
  489.                         buffer[i] = '\0';
  490.                         bTwoCommas = TRUE;
  491.                         break;
  492.                     }
  493.                 }
  494.                 break;
  495.             }
  496.         }
  497.         if(bTwoCommas  &&  lpDrvname != buffer  &&
  498.               STR_EQ(lpDrvname, "pscript")  &&
  499.               !STR_EQ((LPSTR)buffer, lszDevType) )
  500.             lszDevType = buffer;
  501.         else
  502.             lszDevType = "Apple LaserWriter Plus";
  503.     }
  504.  
  505.  
  506.     SetEnvironment(lszFile, (LPSTR)lpdm, sizeof(PSDEVMODE));
  507.  
  508.     if (fWriteProfile)
  509.         WriteProfile(lszFile, lpdm, lpOrigDM, lpProfile);
  510.  
  511.     if (fSendMsg)
  512.         SendMessage(-1, WM_PSDEVMODECHANGE, 0, (LONG)(LPSTR)lszDevType);
  513. }
  514.  
  515.  
  516.  
  517. /**********************************************************************
  518.  * Name: ReadProfile()
  519.  *
  520.  * Action:
  521.  *    Read the device mode parameters from win.ini and fill lpdm
  522.  *    structure with the results.  the win.ini section used is
  523.  *    "Post Script," concatenated with lszFile.  lszFile is a port or an
  524.  *    output file name.  This info gets saved in win.ini when the user
  525.  *    makes changes as well. the first time this is called we try
  526.  *    to match the printer name (lszDevType) to those we know
  527.  *    to auto configure to a certain printer.
  528.  *
  529.  *    things not read from win.ini are set to resonable defaults.
  530.  *
  531.  * note:
  532.  *    some error checking code is to ensure that user changes to
  533.  *    win.ini are not bogus.
  534.  *
  535.  **********************************************************************/
  536.  
  537. void PASCAL ReadProfile(lszFile, lpdm, lszDevType, lpProfile)
  538. LPSTR        lszFile;    /* port used to form win.ini key */
  539. LPPSDEVMODE    lpdm;        /* Far ptr to the device mode info */
  540. LPSTR        lszDevType;
  541. LPSTR        lpProfile;
  542. {
  543.     int    i;
  544.     char    idsBuf[40];
  545.     char    szKey[60];
  546.     PPRINTER pPrinter;
  547.     PPAPER pPaper, pP;
  548.     BOOL rc = TRUE;
  549.  
  550.     SetKey((LPSTR)szKey, lszDevType, lszFile);
  551.  
  552.     DBMSG((">ReadProfile(): file=%ls\n", (LPSTR)lszFile));
  553.  
  554.  
  555.     /* get the printer number from the "device=printer name"
  556.      * section in win.ini */
  557.  
  558.     /* "device" is a resource string */
  559.     LoadString (ghInst, IDS_DEVICE, idsBuf, sizeof(idsBuf));
  560.  
  561.     lpdm->iPrinter = MatchPrinter(lszDevType);
  562.  
  563.     pPrinter = NULL;
  564.  
  565.     if ((lpdm->iPrinter < INT_PRINTER_MIN) ||
  566.         !(pPrinter = GetPrinter(lpdm->iPrinter))) {
  567.         lpdm->iPrinter = DEFAULT_PRINTER;
  568.  
  569.         if (!(pPrinter = GetPrinter(lpdm->iPrinter)))
  570.             return;
  571.  
  572.         lstrcpy(lpdm->dm.dmDeviceName, pPrinter->Name);
  573.     } else {
  574.         lstrcpy(lpdm->dm.dmDeviceName, lszDevType);
  575.     }
  576.  
  577.     LoadString(ghInst, IDS_PRINTERVM, idsBuf, sizeof(idsBuf));
  578.     lpdm->iMaxVM = GetInt(szKey, idsBuf, pPrinter->iMaxVM, lpProfile);
  579.  
  580.     LoadString(ghInst, IDS_FAVORTT, idsBuf, sizeof(idsBuf));
  581.     if(GetInt(szKey, idsBuf, 0, lpProfile))
  582.         lpdm->bFavorTT = TRUE;
  583.     else
  584.         lpdm->bFavorTT = FALSE;
  585.  
  586.     LoadString(ghInst, IDS_LANDSCAPEORIENT, idsBuf, sizeof(idsBuf));
  587.     lpdm->LandscapeOrient = GetInt(szKey, idsBuf, 90, lpProfile);
  588.     if(lpdm->LandscapeOrient != 270)
  589.         lpdm->LandscapeOrient = 90;
  590.  
  591.     LoadString(ghInst, IDS_ENVELOPEORIENT, idsBuf, sizeof(idsBuf));
  592.     lpdm->EnvelopeOrient = GetInt(szKey, idsBuf, 90, lpProfile);
  593.     if(lpdm->EnvelopeOrient != 270)
  594.         lpdm->EnvelopeOrient = 90;
  595.  
  596.     LoadString(ghInst, IDS_RES, idsBuf, sizeof(idsBuf));
  597.     lpdm->iRes = GetInt(szKey, idsBuf, pPrinter->defRes, lpProfile);
  598.  
  599.     LoadString(ghInst, IDS_SCREENFREQUENCY, idsBuf, sizeof(idsBuf));
  600.     lpdm->ScreenFrequency = GetInt(szKey, idsBuf, pPrinter->ScreenFreq, lpProfile);
  601.  
  602.     LoadString(ghInst, IDS_SCREENANGLE, idsBuf, sizeof(idsBuf));
  603.     lpdm->ScreenAngle = GetInt(szKey, idsBuf, pPrinter->ScreenAngle, lpProfile);
  604.  
  605.     LoadString(ghInst, IDS_CUSTOMWIDTH, idsBuf, sizeof(idsBuf));
  606.     lpdm->iCustomWidth = GetInt(szKey, idsBuf, 0, lpProfile);
  607.  
  608.     LoadString(ghInst, IDS_CUSTOMHEIGHT, idsBuf, sizeof(idsBuf));
  609.     lpdm->iCustomHeight = GetInt(szKey, idsBuf, 0, lpProfile);
  610.  
  611.     LoadString(ghInst, IDS_CUSTOMUNIT, idsBuf, sizeof(idsBuf));
  612.     lpdm->dmSizeUnit = GetInt(szKey, idsBuf, 1, lpProfile);
  613.  
  614.     LoadString(ghInst, IDS_MINOUTLINEPPEM, idsBuf, sizeof(idsBuf));
  615.     lpdm->iMinOutlinePPEM = GetInt(szKey, idsBuf, MINOUTLINEPPEM, lpProfile);
  616.  
  617.     lpdm->dm.dmCopies = GetInt(szKey, "Copies", 1, lpProfile);
  618.  
  619.     LoadString(ghInst, IDS_ADVFLAGS, idsBuf, sizeof(idsBuf));
  620.     i = GetInt(szKey, idsBuf,
  621.                    ACCEPTS_TRUETYPE(pPrinter) ? ADVF_TIDEFAULTS : ADVF_DEFAULTS,
  622.                    lpProfile);
  623.  
  624.         lpdm->bNegImage = i & ADVF_NEGIMAGE;
  625.         lpdm->bPerPage = i & ADVF_PERPAGE;
  626.         lpdm->bDSC = i & ADVF_DSC;
  627.  
  628.         if(i & ADVF_TYPE3)
  629.             lpdm->iDLFontFmt = DLFMT_TYPE3 ;
  630.         else if(i & ADVF_TRUETYPE)
  631.             lpdm->iDLFontFmt = DLFMT_TRUETYPE ;
  632.         else
  633.             lpdm->iDLFontFmt = DLFMT_TYPE1 ;
  634.  
  635.     lpdm->bNoDownLoad = i & ADVF_NODOWNLOAD;
  636.  
  637.         lpdm->bSubFonts = (i & ADVF_SUBFONTS) ? TRUE : FALSE;
  638.         lpdm->bMirror = (i & ADVF_MIRROR) ? TRUE : FALSE;
  639.         lpdm->bColorToBlack = (i & ADVF_COLORTOBLACK) ? TRUE : FALSE;
  640.         lpdm->bCompress = (i & ADVF_COMPRESS) ? TRUE : FALSE;
  641.         lpdm->bErrHandler = (i & ADVF_ERRHANDLER) ? TRUE : FALSE;
  642.  
  643.     LoadString(ghInst, IDS_PAPERSOURCE, idsBuf, sizeof(idsBuf));
  644.  
  645.     lpdm->dm.dmDefaultSource = GetInt(szKey, idsBuf, pPrinter->defFeed, lpProfile);
  646.  
  647.     if (lpdm->dm.dmDefaultSource < DMBIN_FIRST ||
  648.         lpdm->dm.dmDefaultSource > DMBIN_LAST)
  649.         lpdm->dm.dmDefaultSource = pPrinter->defFeed;
  650.  
  651.     lpdm->dm.dmPaperSize = GetPaperType(szKey, lpdm->dm.dmDefaultSource, lpProfile);
  652.  
  653.     /* in case user messed up WIN.INI value */
  654.     if (!PaperSupported(pPrinter, lpdm, lpdm->dm.dmPaperSize))
  655.         lpdm->dm.dmPaperSize = GetDefaultPaper();
  656.  
  657.  
  658.     /* search for the paper metrics for the current printer and
  659.      * set the devinit fields accordingly */
  660.  
  661.     pPaper = GetPaperMetrics(pPrinter, lpdm);
  662.  
  663.     if (pPaper) {
  664.  
  665.         for (pP = pPaper; pP->iPaper; pP++)
  666.             if (pP->iPaper == lpdm->dm.dmPaperSize)
  667.                 break;
  668.  
  669.         if (pP->iPaper) {
  670.             lpdm->dm.dmPaperWidth  = Scale(pP->cxPaper, 254, 100);
  671.             lpdm->dm.dmPaperLength = Scale(pP->cyPaper, 254, 100);
  672.  
  673.             DBMSG(("Paper size (in mm) %d %d\n",
  674.                 lpdm->dm.dmPaperWidth, lpdm->dm.dmPaperLength));
  675.         }
  676.  
  677.         LocalFree((HANDLE)pPaper);
  678.     } else {
  679.         DBMSG(("GetPaperMetrics() failed!!\n"));
  680.     }
  681.  
  682.     LoadString (ghInst, IDS_JOBTIMEOUT, idsBuf, sizeof(idsBuf));
  683.     lpdm->iJobTimeout = GetInt(szKey, idsBuf, DEFAULTJOBTIMEOUT, lpProfile);
  684.  
  685.     /* keep positive */
  686.     if (lpdm->iJobTimeout < 0)
  687.         lpdm->iJobTimeout = DEFAULTJOBTIMEOUT;
  688.  
  689.     LoadString (ghInst, IDS_ORIENTATION, idsBuf, sizeof(idsBuf));
  690.     lpdm->dm.dmOrientation = GetInt(szKey, idsBuf, DEFAULTORIENTATION, lpProfile);
  691.  
  692.     if (IS_DUPLEX(pPrinter)) {
  693.         LoadString (ghInst, IDS_DUPLEX, idsBuf, sizeof(idsBuf));
  694.         lpdm->dm.dmDuplex = GetInt(szKey, idsBuf, DEFAULTDUPLEX, lpProfile);
  695.     } else {
  696.         lpdm->dm.dmDuplex = 0;
  697.     }
  698.  
  699.  
  700.     if (pPrinter->fColor) {
  701.         LoadString (ghInst, IDS_COLOR, idsBuf, sizeof(idsBuf));
  702.         lpdm->dm.dmColor = GetInt(szKey, idsBuf, DEFAULT_COLOR, lpProfile);
  703.     } else
  704.         lpdm->dm.dmColor = DMCOLOR_MONOCHROME;
  705.  
  706.  
  707.     for (i = DMBIN_FIRST; i <= DMBIN_LAST; i++) {
  708.  
  709.         lpdm->rgiPaper[i] = GetPaperType(szKey, i, lpProfile);
  710.  
  711.         DBMSG((" ReadProfile(): [%d]%d\n", i, lpdm->rgiPaper[i]));
  712.     }
  713.  
  714.     /* get the header flag */
  715.  
  716.     LoadString (ghInst, IDS_HEADER, idsBuf, sizeof(idsBuf));
  717.     lpdm->fHeader = GetInt(szKey, idsBuf, TRUE, lpProfile);
  718.  
  719.     LoadString (ghInst, IDS_MARGINS, idsBuf, sizeof(idsBuf));
  720.     lpdm->marginState = GetInt(szKey, idsBuf, DEFAULT_MARGINS, lpProfile);
  721.  
  722.     if (lpdm->marginState < DEFAULT_MARGINS || lpdm->marginState > ZERO_MARGINS)
  723.         lpdm->marginState = DEFAULT_MARGINS;
  724.  
  725.     // 2/27/92 - #15648 - Read EPS setting from profile
  726.     GetString(szKey, "EpsFile", NULL, lpdm->EpsFile, CHEPSFILE, lpProfile);
  727.     lpdm->fDoEps = GetInt(szKey, "EPS", FALSE, lpProfile);
  728.  
  729.     lpdm->dm.dmScale = GetInt(szKey, "scale", 100, lpProfile);
  730.  
  731.     DBMSG((" ReadProfile(): iPrinter=%d dmDefaultSource=%d dmPaperSize=%d iRes=%d iJT=%d dmOrient=%d\n",
  732.         lpdm->iPrinter, lpdm->dm.dmDefaultSource, lpdm->dm.dmPaperSize, lpdm->iRes,
  733.         lpdm->iJobTimeout, lpdm->dm.dmOrientation));
  734.  
  735.     FreePrinter(pPrinter);
  736.  
  737.    /* initialize substitution handle to 0 */
  738.    lpdm->hSubTable = 0;
  739.  
  740.     DBMSG(("<ReadProfile() \n"));
  741. }
  742.  
  743.  
  744. void PASCAL WriteProfileInt(lszApp, lszKey, iVal, lpProfile)
  745. LPSTR    lszApp;
  746. LPSTR    lszKey;
  747. int    iVal;
  748. LPSTR    lpProfile;
  749. {
  750.     char    sz[10];
  751.  
  752.     wsprintf(sz, "%d", iVal);
  753.  
  754.     WriteString(lszApp, lszKey, sz, lpProfile);
  755. }
  756.  
  757.  
  758. /*******************************************************************
  759.  * Name: WriteProfile()
  760.  *
  761.  * Action: Write the device mode parameters out to win.ini.
  762.  *
  763.  *******************************************************************/
  764.  
  765. void PASCAL WriteProfile(lszFile, lpdm, lpOrigDM, lpProfile)
  766. LPSTR        lszFile;    /* Ptr to the com port's file name */
  767. LPPSDEVMODE    lpdm;        /* new PSDEVMODE to write */
  768. LPPSDEVMODE    lpOrigDM;    /* old copy to save unnecessary writes */
  769. LPSTR        lpProfile;
  770. {
  771.     char    szKey[64];
  772.     char    sz[64];
  773.     char    idsBuf[40];
  774.     char    buf[10];    /* used for wsprintf */
  775.     int    i,iFeed;
  776.     PPRINTER pPrinter;
  777.     PPRINTER pOrigPrinter;
  778.  
  779.     DBMSG((">WriteProfile()\n"));
  780.  
  781.  
  782.     if (!(pPrinter = GetPrinter(lpdm->iPrinter)))
  783.         return;
  784.  
  785.     if (!(pOrigPrinter = GetPrinter(lpOrigDM->iPrinter))) {
  786.         FreePrinter(pPrinter);
  787.         return;
  788.     }
  789.     // save under [<custom name>,<port>]
  790.     SetKey((LPSTR)szKey, (LPSTR)lpdm->dm.dmDeviceName, lszFile);
  791.         if (lpdm->iMaxVM != lpOrigDM->iMaxVM) {
  792.         LoadString(ghInst, IDS_PRINTERVM, idsBuf, sizeof(idsBuf));
  793.             WriteProfileInt(szKey, idsBuf, lpdm->iMaxVM, lpProfile);
  794.         }
  795.  
  796.         if (lpdm->iRes != lpOrigDM->iRes) {
  797.         LoadString(ghInst, IDS_RES, idsBuf, sizeof(idsBuf));
  798.             WriteProfileInt(szKey, idsBuf, lpdm->iRes, lpProfile);
  799.         }
  800.  
  801.         if (lpdm->ScreenFrequency != lpOrigDM->ScreenFrequency) {
  802.         LoadString(ghInst, IDS_SCREENFREQUENCY, idsBuf, sizeof(idsBuf));
  803.             WriteProfileInt(szKey, idsBuf, lpdm->ScreenFrequency, lpProfile);
  804.         }
  805.  
  806.         if (lpdm->ScreenAngle != lpOrigDM->ScreenAngle) {
  807.         LoadString(ghInst, IDS_SCREENANGLE, idsBuf, sizeof(idsBuf));
  808.             WriteProfileInt(szKey, idsBuf, lpdm->ScreenAngle, lpProfile);
  809.         }
  810.  
  811.         if (lpdm->iCustomWidth != lpOrigDM->iCustomWidth) {
  812.             LoadString(ghInst, IDS_CUSTOMWIDTH, idsBuf, sizeof(idsBuf));
  813.             WriteProfileInt(szKey, idsBuf, lpdm->iCustomWidth, lpProfile);
  814.         }
  815.  
  816.         if (lpdm->iCustomHeight != lpOrigDM->iCustomHeight) {
  817.             LoadString(ghInst, IDS_CUSTOMHEIGHT, idsBuf, sizeof(idsBuf));
  818.             WriteProfileInt(szKey, idsBuf, lpdm->iCustomHeight, lpProfile);
  819.         }
  820.  
  821.         if (lpdm->dmSizeUnit != lpOrigDM->dmSizeUnit) {
  822.             LoadString(ghInst, IDS_CUSTOMUNIT, idsBuf, sizeof(idsBuf));
  823.             WriteProfileInt(szKey, idsBuf, lpdm->dmSizeUnit, lpProfile);
  824.         }
  825.  
  826.         if (lpdm->bNegImage != lpOrigDM->bNegImage
  827.             || lpdm->bPerPage != lpOrigDM->bPerPage
  828.             || lpdm->bDSC != lpOrigDM->bDSC
  829.             || lpdm->iDLFontFmt != lpOrigDM->iDLFontFmt
  830.             || lpdm->bSubFonts != lpOrigDM->bSubFonts
  831.             || lpdm->bMirror != lpOrigDM->bMirror
  832.             || lpdm->bColorToBlack != lpOrigDM->bColorToBlack
  833.             || lpdm->bCompress != lpOrigDM->bCompress
  834.             || lpdm->bErrHandler != lpOrigDM->bErrHandler
  835.            ) {
  836.  
  837.         LoadString(ghInst, IDS_ADVFLAGS, idsBuf, sizeof(idsBuf));
  838.  
  839.             switch(lpdm->iDLFontFmt)
  840.             {
  841.                 case  DLFMT_TYPE3:
  842.                     i = ADVF_TYPE3;
  843.                     break;
  844.                 case  DLFMT_TRUETYPE:
  845.                     i = ADVF_TRUETYPE;
  846.                     break;
  847.                 default:
  848.                     i = ADVF_TYPE1;
  849.                     break;
  850.             }
  851.  
  852.  
  853.             i |= (lpdm->bNegImage ? ADVF_NEGIMAGE : 0)
  854.                 | (lpdm->bPerPage ? ADVF_PERPAGE : 0)
  855.                 | (lpdm->bDSC ? ADVF_DSC : 0)
  856.                 | (lpdm->bSubFonts ? ADVF_SUBFONTS : 0)
  857.                 | (lpdm->bMirror ? ADVF_MIRROR : 0)
  858.                 | (lpdm->bColorToBlack ? ADVF_COLORTOBLACK : 0)
  859.                 | (lpdm->bCompress ? ADVF_COMPRESS : 0)
  860.                 | (lpdm->bErrHandler ? ADVF_ERRHANDLER : 0)
  861.         | (lpdm->bNoDownLoad ? ADVF_NODOWNLOAD : 0)
  862.                 ;
  863.  
  864.             WriteProfileInt(szKey, idsBuf, i, lpProfile);
  865.         }
  866.  
  867.     if (lpdm->dm.dmOrientation != lpOrigDM->dm.dmOrientation) {
  868.  
  869.         DBMSG_WP((" WriteProfile(): %ls %d\n",
  870.             (LPSTR)idsBuf, lpdm->dm.dmOrientation == DMORIENT_LANDSCAPE));
  871.  
  872.         LoadString(ghInst, IDS_ORIENTATION, idsBuf, sizeof(idsBuf));
  873.         WriteProfileInt(szKey, idsBuf, lpdm->dm.dmOrientation, lpProfile);
  874.     }
  875.  
  876.     if (lpdm->dm.dmDuplex != lpOrigDM->dm.dmDuplex) {
  877.         LoadString(ghInst, IDS_DUPLEX, idsBuf, sizeof(idsBuf));
  878.         WriteProfileInt(szKey, idsBuf, lpdm->dm.dmDuplex, lpProfile);
  879.     }
  880.  
  881.     if (lpdm->dm.dmColor != lpOrigDM->dm.dmColor) {
  882.         LoadString(ghInst, IDS_COLOR, idsBuf, sizeof(idsBuf));
  883.         WriteProfileInt(szKey, idsBuf, lpdm->dm.dmColor, lpProfile);
  884.     }
  885.  
  886.  
  887.     if (lpdm->iJobTimeout != lpOrigDM->iJobTimeout) {
  888.         LoadString(ghInst, IDS_JOBTIMEOUT, idsBuf, sizeof(idsBuf));
  889.         WriteProfileInt(szKey, idsBuf, lpdm->iJobTimeout, lpProfile);
  890.     }
  891.  
  892.     /* save the paper source, i.e. upper, lower or ... */
  893.     if (lpdm->dm.dmDefaultSource != lpOrigDM->dm.dmDefaultSource) {
  894.         DBMSG_WP((" WriteProfile(): %ls %d\n", (LPSTR)idsBuf, lpdm->iFeed));
  895.  
  896.         LoadString(ghInst, IDS_PAPERSOURCE, idsBuf, sizeof(idsBuf));
  897.         WriteProfileInt(szKey, idsBuf, lpdm->dm.dmDefaultSource, lpProfile);
  898.     }
  899.  
  900.     if (lpdm->fHeader != lpOrigDM->fHeader) {
  901.  
  902.         LoadString(ghInst, IDS_HEADER, sz, sizeof(sz));
  903.         WriteProfileInt(szKey, sz, lpdm->fHeader, lpProfile);
  904.  
  905.         DBMSG_WP((" WriteProfile(): %ls %ls\n", (LPSTR)idsBuf, (LPSTR)sz));
  906.     }
  907.  
  908.     if (lpdm->marginState != lpOrigDM->marginState) {
  909.  
  910.         LoadString(ghInst, IDS_MARGINS, sz, sizeof(sz));
  911.         WriteProfileInt(szKey, sz, lpdm->marginState, lpProfile);
  912.  
  913.         DBMSG_WP((" WriteProfile(): marginState %d\n", lpdm->marginState));
  914.     }
  915.  
  916.     /* For each feed available to the printer save the paper
  917.      * associated with it.
  918.      */
  919.     LoadString(ghInst, IDS_PAPERX, buf, sizeof(buf));
  920.  
  921.     for (iFeed = DMBIN_FIRST; iFeed <= DMBIN_LAST; iFeed++) {
  922.  
  923.         if (pPrinter->feed[iFeed - DMBIN_FIRST]) {
  924.             wsprintf(idsBuf, buf, iFeed);
  925.  
  926.             DBMSG_WP((" WriteProfile(): [%d]%d %ls\n",
  927.                 iFeed, lpdm->rgiPaper[iFeed], (LPSTR)idsBuf));
  928.  
  929.             DBMSG_WP((" WriteProfile(): %ls %ls\n",
  930.                 (LPSTR)idsBuf, (LPSTR)sz));
  931.  
  932.             WriteProfileInt(szKey, idsBuf, lpdm->rgiPaper[iFeed], lpProfile);
  933.  
  934.         } else if (pOrigPrinter->feed[iFeed - DMBIN_FIRST] && !pPrinter->feed[iFeed - DMBIN_FIRST]) {
  935.  
  936.             /* null it out in case it isn't used by the new printer */
  937.  
  938.             WriteString(szKey, idsBuf, szNull, lpProfile);
  939.         }
  940.     }
  941.  
  942.     if (lpdm->dm.dmCopies != lpOrigDM->dm.dmCopies)
  943.         WriteProfileInt(szKey, "Copies", lpdm->dm.dmCopies, lpProfile);
  944.  
  945.     if (lpdm->fDoEps != lpOrigDM->fDoEps)
  946.         WriteProfileInt(szKey, "EPS", (lpdm->fDoEps? 1: 0), lpProfile);
  947.  
  948.     WriteProfileString(szKey, "EpsFile", (LPSTR)lpdm->EpsFile);
  949.  
  950.     if (lpdm->dm.dmScale != lpOrigDM->dm.dmScale)
  951.         WriteProfileInt(szKey, "scale", lpdm->dm.dmScale, lpProfile);
  952.  
  953.     FreePrinter(pOrigPrinter);
  954.     FreePrinter(pPrinter);
  955.  
  956.     DBMSG_WP(("<WriteProfile()\n"));
  957.     return;
  958. }
  959.  
  960.  
  961. /********************************************************************/
  962.  
  963. short    FAR PASCAL GetDefaultPaper()
  964. {
  965.     if (isUSA())
  966.         return(DMPAPER_LETTER);    /* US LETTER */
  967.     else
  968.         return(DMPAPER_A4);    /* DIN A4 */
  969. }
  970.  
  971.  
  972.  
  973. /***********************************************************************
  974. * Name: GetPaperType()
  975. *
  976. * Action: Get the paper type from win.ini for feeder iFeed
  977. *
  978. * return the default
  979. *
  980. ************************************************************************/
  981.  
  982. int PASCAL GetPaperType(szKey, iFeed, lpProfile)
  983. LPSTR    szKey;
  984. int    iFeed;      /* The tray from which the paper is being fed */
  985. LPSTR    lpProfile;
  986. {
  987.     char    idsBuf[10];
  988.     char    feed[10];
  989.     int    val;
  990.  
  991.     LoadString (ghInst, IDS_PAPERX, feed, sizeof(feed));
  992.  
  993.     wsprintf(idsBuf, feed, iFeed);
  994.  
  995.     val = GetInt(szKey, idsBuf, GetDefaultPaper(), lpProfile);
  996.  
  997.     return val;
  998. }
  999.  
  1000.  
  1001.  
  1002. /*
  1003.  * int FAR PASCAL GetExternPrinter(int iExtPrinterNum)
  1004.  *
  1005.  * returns file handel for external printer (-1 if it doesn't exist)
  1006.  *
  1007.  * uses the section in win.in that looks like this:
  1008.  *
  1009.  *    [PSCRIPT]
  1010.  *    External Printers=1
  1011.  *    printer1=FILENAME
  1012.  *
  1013.  * in:
  1014.  *    i    external printer index (1 - N)
  1015.  *
  1016.  * return:
  1017.  *    fh    of external printer (.WPD) file
  1018.  */
  1019.  
  1020. int FAR PASCAL GetExternPrinter(int i)
  1021. {
  1022.     OFSTRUCT os;
  1023.     char    temp[66];
  1024.  
  1025.     DBMSG(("GetExternPrinter() %d\n", i));
  1026.  
  1027.         GetExternPrinterFilename(i, temp);
  1028.      return OpenFile(temp, &os, OF_READ);
  1029. }
  1030.  
  1031.  
  1032. void FAR PASCAL GetExternPrinterFilename(int i, LPSTR lpFilename)
  1033. {
  1034.     OFSTRUCT os;
  1035.     short   fh;
  1036.     char    temp[40];
  1037.     char    idsBuf[12];
  1038.     char    szPrinter[20];
  1039.     LPSTR   lpszFilename;
  1040.  
  1041.     DBMSG(("GetExternPrinterFilename() %d\n", i));
  1042.  
  1043.     LoadString (ghInst, IDS_PRINTER, idsBuf, sizeof(idsBuf));
  1044.     wsprintf(temp, idsBuf, i);
  1045.  
  1046.     GetProfileString(szModule, temp, szNull, szPrinter, sizeof(szPrinter));
  1047.  
  1048.     DBMSG(("GetExternPrinter %d %ls\n", i, (LPSTR)szPrinter));
  1049.  
  1050.     GetSystemDirectory(lpFilename, 160);
  1051.     lpszFilename = lpFilename + lstrlen(lpFilename);
  1052.     lpszFilename = AnsiPrev(lpFilename, lpszFilename);
  1053.     if (*lpszFilename != '\\') 
  1054.     {
  1055.         lpszFilename = AnsiNext(lpszFilename);
  1056.         *lpszFilename = '\\';
  1057.     }
  1058.     lpszFilename = AnsiNext(lpszFilename);
  1059.     *lpszFilename = '\0';
  1060.     lstrcat(lpFilename, szPrinter);
  1061.      lstrcat(lpFilename, szRes);
  1062.  
  1063.      if((fh = OpenFile(lpFilename, &os, OF_READ)) > -1)
  1064.     {
  1065.         _lclose(fh);
  1066.         return;
  1067.     }
  1068.     //  if there is no WPD file in the system directory
  1069.     //  try looking in the windows directory.
  1070.  
  1071.     GetWindowsDirectory(lpFilename, 160);
  1072.     lpszFilename = lpFilename + lstrlen(lpFilename);
  1073.     lpszFilename = AnsiPrev(lpFilename, lpszFilename);
  1074.     if (*lpszFilename != '\\') 
  1075.     {
  1076.         lpszFilename = AnsiNext(lpszFilename);
  1077.         *lpszFilename = '\\';
  1078.     }
  1079.     lpszFilename = AnsiNext(lpszFilename);
  1080.     *lpszFilename = '\0';
  1081.     lstrcat(lpFilename, szPrinter);
  1082.      lstrcat(lpFilename, szRes);
  1083. }
  1084.  
  1085. int FAR PASCAL SubTabProc(LPLOGFONT lplf, LPTEXTMETRIC lptm, short nType,
  1086.                            LPSTR dwData)
  1087. {
  1088.     // this procedue is called so there must be a device font.
  1089.     return 0;
  1090. }
  1091.  
  1092. int FAR PASCAL SubTabTTProc(LPLOGFONT lplf, LPTEXTMETRIC lptm, short nType,
  1093.                LPSTR lpstr)
  1094. {
  1095.     LPSUBTAB lpTable;
  1096.     short   i, nSub;
  1097.  
  1098.     lpTable = (LPSUBTAB) lpstr;
  1099.     nSub = lpTable->nSub;
  1100.     for (i = 0; i < nSub; i++)
  1101.     {
  1102.         // we are happy, the tt font is already in the table
  1103.         if (!lstrcmpi(lplf->lfFaceName, lpTable->SubEnt[i].rgTTFont))
  1104.             return 1;
  1105.     }
  1106.  
  1107.     if (nSub >= lpTable->MaxSub)
  1108.         return 0;
  1109.     lstrcpy(lpTable->SubEnt[nSub].rgTTFont, lplf->lfFaceName);
  1110.     lpTable->SubEnt[nSub].rgDevFont[0] = '\0';
  1111.     lpTable->nSub++;
  1112.     return 1;
  1113. }
  1114.  
  1115. LPSUBTAB FAR PASCAL LockSubTable(lpdv, bUser)
  1116. LPDV    lpdv;
  1117. int bUser;
  1118. {
  1119.     LPSUBTAB lpTable;
  1120.     LPSUBENTRY lpCurEntry;
  1121.     char szBuf[66];
  1122.     LPSTR lpsz;
  1123.     int i;
  1124.  
  1125.     if (lpdv->DevMode.hSubTable)
  1126.         lpTable = (LPSUBTAB)GlobalLock(lpdv->DevMode.hSubTable);
  1127.     else
  1128.         lpTable = NULL;
  1129.  
  1130.     if (lpTable && lpTable->bUser == bUser)
  1131.     goto done;
  1132.  
  1133.     if (!lpTable || bUser == 0)
  1134.     // build default lpTable
  1135.     {
  1136.         if (!lpTable)
  1137.         {
  1138.             lpdv->DevMode.hSubTable = GlobalAlloc(GDLLHND, sizeof(SUBTAB) + IDS_NUMDEFSUBS * 2 * sizeof(SUBENTRY));
  1139.             if (lpTable = (LPSUBTAB) GlobalLock(lpdv->DevMode.hSubTable))
  1140.             {
  1141.                 lpTable->MaxSub = IDS_NUMDEFSUBS * 2;
  1142.                 // LHND make it zero-init
  1143.                 // lpTable->bUser = 0;
  1144.                 // lpTable->nSub = 0;
  1145.             }
  1146.         }
  1147.  
  1148.         lpCurEntry = lpTable->SubEnt;
  1149.  
  1150.         // Initialize with Default table
  1151.         for (i = 0; ; i++, lpCurEntry++)
  1152.         {
  1153.             if (!LoadString(ghInst, IDS_DEFSUBBASE + i, szBuf, sizeof(szBuf)))
  1154.                 break;
  1155.  
  1156.             /* find the comma & change it to NULL */
  1157.             for (lpsz = szBuf; *lpsz != ','; lpsz = AnsiNext(lpsz))
  1158.                 ;
  1159.             *lpsz++ = '\0';
  1160.  
  1161.             /* our two strings are now pointed to by szBuf & lpsz, resp. */
  1162.             lstrcpy(lpCurEntry->rgTTFont,szBuf);
  1163.             lstrcpy(lpCurEntry->rgDevFont,lpsz);
  1164.  
  1165.             // make sure that this device font is available on the device
  1166.             //  EnumFonts returns 1 to indicate failure.
  1167.  
  1168.             if (!EnumFonts(lpdv, lpsz, SubTabProc, (LPSTR)lpCurEntry,
  1169.                 ENUM_INTERNAL | ENUM_SOFTFONTS))
  1170.                 continue;
  1171.  
  1172.             // need to try the TrueType font name itself.
  1173.             if (!EnumFonts(lpdv, (LPSTR)szBuf, SubTabProc, (LPSTR)lpCurEntry,
  1174.                 ENUM_INTERNAL | ENUM_SOFTFONTS))
  1175.             {
  1176.                 lstrcpy(lpCurEntry->rgDevFont, szBuf);
  1177.                 continue;
  1178.             }
  1179.  
  1180.             // oops nothing is available, no substitution
  1181.         }
  1182.  
  1183.         lpTable->nSub = i;
  1184.  
  1185.         // add TT font which are not in the default substitution table
  1186.         while (!EnumFonts(lpdv, 0, SubTabTTProc, (LPSTR)lpTable, ENUM_TRUETYPE))
  1187.         {
  1188.             HANDLE hNew;
  1189.             int     xSub;
  1190.  
  1191.             xSub = lpTable->MaxSub + IDS_NUMDEFSUBS;
  1192.  
  1193.             GlobalUnlock(lpdv->DevMode.hSubTable);
  1194.  
  1195.             hNew = GlobalReAlloc(lpdv->DevMode.hSubTable, sizeof(SUBTAB) + xSub * sizeof(SUBENTRY),
  1196.                                 LMEM_MOVEABLE);
  1197.             if (hNew)
  1198.             {
  1199.                 lpdv->DevMode.hSubTable = hNew;
  1200.                 lpTable = (LPSUBTAB) GlobalLock(hNew);
  1201.                 lpTable->MaxSub = xSub;
  1202.             }
  1203.             else
  1204.                 // cut off additional tt fonts due to low memory
  1205.                 break;
  1206.         }
  1207.     }
  1208.  
  1209.     // Apply user entries from win.ini
  1210.     if (bUser)
  1211.     {
  1212.         lpCurEntry = lpTable->SubEnt;
  1213.         for (i = 0; i < lpTable->nSub; i++, lpCurEntry++)
  1214.         {
  1215.             // subtable entry >= IDS_NUMDEFSUBS, no entry in win.ini means
  1216.             //    to download
  1217.             // subtable entry < IDS_NUMDEFSUBS, no entry in win.ini means
  1218.             //    to use default table
  1219.             if (GetProfileString(szModule, lpCurEntry->rgTTFont, "", szBuf, sizeof(szBuf)))
  1220.             {
  1221.                 // This device font is available
  1222.                 if (!EnumFonts(lpdv, szBuf, SubTabProc, (LPSTR)lpCurEntry,
  1223.                         ENUM_INTERNAL | ENUM_SOFTFONTS))
  1224.                     lstrcpy(lpCurEntry->rgDevFont, szBuf);
  1225.                 else            // key word for downloading
  1226.                     if (szBuf[0] == '0')
  1227.                         lpCurEntry->rgDevFont[0] = '\0';
  1228.                 lpTable->bUser = bUser;
  1229.             }
  1230.             // found no entry in win.ini, no need to do anything.
  1231.             // use the default table or download if not found in default table.
  1232.         }
  1233.     }
  1234.  
  1235. done:
  1236.     return lpTable;
  1237. }
  1238.  
  1239.  
  1240. BOOL   FAR PASCAL UpdateSubTable(lpdv, hwndTT, hwndDV)
  1241. LPDV  lpdv;
  1242. HWND  hwndTT, hwndDV;
  1243. {
  1244.     int  i, index, iDevFont;
  1245.     LPSUBTAB   lpTable;
  1246.     LPSUBENTRY lpCurEntry;
  1247.  
  1248.     // start with default table
  1249.     lpTable = LockSubTable(lpdv, 0);
  1250.  
  1251.     lpCurEntry = lpTable->SubEnt;
  1252.  
  1253.     // Update with mapping from ListBox
  1254.     for (i = 0; i < lpTable->nSub; ++i, lpCurEntry++)
  1255.     {
  1256.     index = (int)SendMessage(hwndTT, LB_FINDSTRING, -1, (DWORD)((LPSTR)lpCurEntry->rgTTFont));
  1257.  
  1258.     if (index < 0)
  1259.         continue;
  1260.  
  1261.     iDevFont = (int)SendMessage(hwndTT, LB_GETITEMDATA, index, 0L);
  1262.  
  1263.     // user wants to download
  1264.         if (!iDevFont)
  1265.         lpCurEntry->rgDevFont[0] = '\0';
  1266.     else
  1267.         SendMessage(hwndDV, LB_GETTEXT, iDevFont, (DWORD)((LPSTR)lpCurEntry->rgDevFont));
  1268.     }
  1269.  
  1270.     lpTable->bUser = 1;
  1271.  
  1272.     UnlockSubTable(lpdv);
  1273.     return(TRUE);
  1274. }
  1275.  
  1276.  
  1277. void FAR PASCAL UnlockSubTable(lpdv)
  1278. LPDV    lpdv;
  1279. {
  1280.     if (lpdv->DevMode.hSubTable)
  1281.     GlobalUnlock(lpdv->DevMode.hSubTable);
  1282. }
  1283.  
  1284.  
  1285. void FAR PASCAL FreeSubTable(lpdv)
  1286. LPDV    lpdv;
  1287. {
  1288.     if (lpdv->DevMode.hSubTable)
  1289.     {
  1290.     GlobalFree(lpdv->DevMode.hSubTable);
  1291.     lpdv->DevMode.hSubTable = NULL;
  1292.     }
  1293. }
  1294.  
  1295. void FAR PASCAL WriteSubTable(lpdv)
  1296. LPDV    lpdv;
  1297. {
  1298.     LPSUBTAB lpTable = NULL;
  1299.     LPSUBENTRY lpCurEntry;
  1300.     int i;
  1301.  
  1302.     lpTable = (LPSUBTAB) GlobalLock(lpdv->DevMode.hSubTable);
  1303.  
  1304.     if (!lpTable)
  1305.     return;
  1306.  
  1307.     lpCurEntry = lpTable->SubEnt;
  1308.  
  1309.     for (i = 0; i < lpTable->nSub; ++i, lpCurEntry++)
  1310.     {
  1311.             /* write it */
  1312.         if (lpCurEntry->rgDevFont[0])
  1313.             WriteProfileString(szModule, lpCurEntry->rgTTFont, lpCurEntry->rgDevFont);
  1314.         // over-write default substitution table with download
  1315.         else  //  this TT font is mapped to "download as softfont"
  1316.         {
  1317.             if (i < IDS_NUMDEFSUBS)
  1318.                 WriteProfileString(szModule, lpCurEntry->rgTTFont, "0");
  1319.             else
  1320.                 WriteProfileString(szModule, lpCurEntry->rgTTFont, NULL);
  1321.         }
  1322.     }
  1323.  
  1324.     GlobalUnlock(lpdv->DevMode.hSubTable);
  1325. }
  1326.  
  1327.  
  1328. BOOL FAR PASCAL FindSubFont(lpdv, bUser, lpszTTFont, lpszDevFont)
  1329. LPDV lpdv;
  1330. BOOL    bUser;
  1331. LPSTR lpszTTFont;
  1332. LPSTR lpszDevFont;
  1333. {
  1334.     LPSUBTAB     lpTable;
  1335.     LPSUBENTRY     lpCurEnt;
  1336.     int     i, nSub;
  1337.     BOOL    bSub = FALSE;
  1338.  
  1339.     lpTable = (LPSUBTAB) LockSubTable(lpdv, bUser);
  1340.  
  1341.     if (!lpTable)
  1342.         return NULL;
  1343.  
  1344.     nSub = lpTable->nSub;
  1345.  
  1346.     lpCurEnt = lpTable->SubEnt;
  1347.  
  1348.     for (i = 0; i < nSub; ++i, lpCurEnt++)
  1349.     if (!lstrcmpi(lpszTTFont, lpCurEnt->rgTTFont))
  1350.         {
  1351.         if (lpCurEnt->rgDevFont)
  1352.         {
  1353.         lstrcpy(lpszDevFont, lpCurEnt->rgDevFont);
  1354.         bSub = TRUE;
  1355.         }
  1356.         break;
  1357.         }
  1358.  
  1359.     UnlockSubTable(lpdv);
  1360.  
  1361.     return bSub;
  1362. }
  1363.  
  1364.  
  1365.  
  1366. LPSTR   NEAR  PASCAL  SetOldKey(LPSTR  key, LPSTR  lszPort);
  1367. void   NEAR  PASCAL  StripColon(LPSTR  lszPort);
  1368. BOOL  NEAR  PASCAL  DupProfileSection(LPSTR  lpOldSec,
  1369.                             LPSTR  lpNewSec);
  1370. LPSTR  NEAR  PASCAL   Transfer(LPSTR  buffer1, LPSTR  lszPort);
  1371.  
  1372.  
  1373.  
  1374. BOOL  FAR  PASCAL  DevInstall(hWnd, lszModelName, lszOldPort, lszNewPort)
  1375. HWND   hWnd;
  1376. LPSTR  lszModelName, lszOldPort, lszNewPort;
  1377. {
  1378.     BYTE  buffer1[80], buffer2[80];
  1379.  
  1380.     lszOldPort = Transfer(buffer1, lszOldPort);
  1381.     lszNewPort = Transfer(buffer2, lszNewPort);
  1382.  
  1383.     StripColon(lszOldPort);
  1384.     StripColon(lszNewPort);
  1385.  
  1386.     if(lszNewPort)   // ATM specific things
  1387.     {
  1388.         BYTE  atmPath[156];
  1389.         WORD  len;
  1390.         OFSTRUCT  oaf;
  1391.  
  1392.  
  1393.         // fix for bug num 13051
  1394.  
  1395.         GetWindowsDirectory(atmPath, 144);
  1396.         len = lstrlen(atmPath);
  1397.         if(atmPath[len - 1] != '\\')
  1398.             lstrcat(atmPath, "\\");
  1399.         lstrcat(atmPath, "atm.ini");
  1400.         if(OpenFile(atmPath, (LPOFSTRUCT)(&oaf), OF_EXIST) > -1)
  1401.         {
  1402.             WritePrivateProfileString("Aliases", "Times Roman", "Times",
  1403.                 atmPath);
  1404.             WritePrivateProfileString("Synonyms", "Times Roman", "Times",
  1405.                 atmPath);
  1406.         }
  1407.  
  1408.     }
  1409.  
  1410.     if(lszOldPort && lszNewPort)
  1411.     {   // rename new style printer in win.ini
  1412.         BYTE  NewKey[40], OldKey[40];
  1413.  
  1414.         if(!lstrcmp(lszOldPort ,lszNewPort))
  1415.             return(FALSE);  //  do nothing - bug in Control Panel
  1416.         SetOldKey(OldKey, lszNewPort);
  1417.         WriteProfileString(OldKey, (LPSTR)"ATM", (LPSTR)"placeholder");
  1418.  
  1419.         SetKey(OldKey, lszModelName, lszOldPort);
  1420.         SetKey(NewKey, lszModelName, lszNewPort);
  1421.  
  1422.         DupProfileSection(OldKey, NewKey);
  1423.  
  1424.         return(WriteProfileString(OldKey, NULL, NULL));
  1425.         // delete  entire section in Win.ini
  1426.     }
  1427.     else if(lszOldPort && !lszNewPort)
  1428.     {   //  remove new style printer from win.ini
  1429.         BYTE  OldKey[40];
  1430.  
  1431.         SetKey(OldKey, lszModelName, lszOldPort);
  1432.  
  1433.         return(WriteProfileString(OldKey, NULL, NULL));
  1434.         // delete  entire section in Win.ini
  1435.     }
  1436.     else if(!lszOldPort && lszNewPort)
  1437.     {   //  install new printer
  1438.         //  if first time install, (Distinguished by absence of
  1439.         //  ATM=placeholder , consider this to be an upgrade
  1440.         //  else its a plain install.
  1441.  
  1442.         BYTE  NewKey[40], OldKey[40];
  1443.         WORD   iPaper, iFeed;
  1444.  
  1445.         SetOldKey(OldKey, lszNewPort);
  1446.  
  1447.         //  call GetProfileString just to see if section exists
  1448.         if(!GetProfileString(OldKey, NULL, "", NewKey, 40))
  1449.         {
  1450.             WriteProfileString(OldKey, (LPSTR)"ATM", (LPSTR)"placeholder");
  1451.             //  create this section - which is needed to install ATM
  1452.             return(FALSE);    // Oldkey section  is missing
  1453.         }
  1454.  
  1455.         GetProfileString(OldKey, "ATM", "Upgrade", NewKey, 40);
  1456.         //  NewKey contains either Upgrade or placeholder
  1457.  
  1458.         if(lstrcmp("Upgrade", NewKey))
  1459.             return(FALSE);
  1460.  
  1461.  
  1462.         //  now we get down to business of modifying win.ini
  1463.  
  1464.         SetKey(NewKey, lszModelName, lszNewPort);
  1465.  
  1466.         WriteProfileString(OldKey, "device", NULL);
  1467.         // delete  entry  device=...
  1468.  
  1469.         DupProfileSection(OldKey, NewKey);
  1470.  
  1471.         //-------convert 3.0 binnumbers to 3.1--------
  1472.         //               bug 10047
  1473.         //  first delete obsolete paper feeds
  1474.  
  1475.         WriteProfileString(NewKey, "feed2", NULL);
  1476.         WriteProfileString(NewKey, "feed3", NULL);
  1477.         WriteProfileString(NewKey, "feed4", NULL);
  1478.         WriteProfileString(NewKey, "feed12", NULL);
  1479.         WriteProfileString(NewKey, "feed13", NULL);
  1480.         WriteProfileString(NewKey, "feed15", NULL);
  1481.  
  1482.         //  now create the new paper feeds
  1483.  
  1484.         if(iPaper = GetProfileInt(OldKey, "feed2", 0) )
  1485.             WriteProfileInt(NewKey, "feed1", iPaper, NULL);
  1486.         if(iPaper = GetProfileInt(OldKey, "feed3", 0) )
  1487.             WriteProfileInt(NewKey, "feed2", iPaper, NULL);
  1488.         if(iPaper = GetProfileInt(OldKey, "feed4", 0) )
  1489.             WriteProfileInt(NewKey, "feed3", iPaper, NULL);
  1490.         if(iPaper = GetProfileInt(OldKey, "feed12", 0) )
  1491.             WriteProfileInt(NewKey, "feed9", iPaper, NULL);
  1492.         if(iPaper = GetProfileInt(OldKey, "feed13", 0) )
  1493.             WriteProfileInt(NewKey, "feed10", iPaper, NULL);
  1494.         if(iPaper = GetProfileInt(OldKey, "feed15", 0) )
  1495.             WriteProfileInt(NewKey, "feed4", iPaper, NULL);
  1496.  
  1497.         //  may need to alter arg to 'source'
  1498.  
  1499.         iFeed = GetProfileInt(OldKey, "source", 0);
  1500.         switch (iFeed)
  1501.         {
  1502.             case 2:
  1503.               iFeed = 1;
  1504.               break;
  1505.             case 3:
  1506.               iFeed = 2;
  1507.               break;
  1508.             case 4:
  1509.               iFeed = 3;
  1510.               break;
  1511.             case 12:
  1512.               iFeed = 9;
  1513.               break;
  1514.             case 13:
  1515.               iFeed = 10;
  1516.               break;
  1517.             case 15:
  1518.               iFeed = 4;
  1519.               break;
  1520.         }
  1521.         WriteProfileInt(NewKey, "source", iFeed, NULL);
  1522.  
  1523.  
  1524.  
  1525.         // ensure that the lines
  1526.         // [PostScript,Port]
  1527.         // dummy=placeholder
  1528.         // exists in win.ini   required for Adobe ATM to install.
  1529.         // also marks this Old section as being already upgraded.
  1530.  
  1531.         WriteProfileString(OldKey, (LPSTR)"ATM", (LPSTR)"placeholder");
  1532.         return(TRUE);  // Finally - we upgraded!
  1533.     }
  1534.     return(FALSE);  // undefined operation.
  1535. }
  1536.  
  1537.  
  1538.  
  1539. //-------- SetOldKey ----------------------
  1540. //  creates old style format Section Keys
  1541. //  for postscript printers
  1542. //  expects that terminating : have been
  1543. //  removed.
  1544. //-----------------------------------------
  1545.  
  1546. LPSTR   NEAR  PASCAL  SetOldKey(key, lszPort)
  1547. LPSTR  key, lszPort;
  1548. {
  1549.     lstrcpy(key, "PostScript,");
  1550.     lstrcat(key, lszPort);
  1551.     return(key);
  1552. }
  1553.  
  1554. void   NEAR  PASCAL  StripColon(lszPort)
  1555. LPSTR  lszPort;
  1556. {
  1557.     //  strip terminating :  from port names (if not NULL).
  1558.     if(lszPort)
  1559.     {
  1560.         WORD   len;
  1561.         len = lstrlen(lszPort);
  1562.         if(len  &&  lszPort[len-1] == ':')
  1563.             lszPort[len-1] = '\0';
  1564.     }
  1565. }
  1566.  
  1567.  
  1568. #define KEY_BUF_SIZE_INC    256
  1569. #define MAX_STRING_LENGTH   128
  1570.  
  1571.  
  1572. BOOL  NEAR  PASCAL  DupProfileSection(lpOldSec, lpNewSec)
  1573. LPSTR   lpOldSec, lpNewSec;
  1574. {
  1575.     HANDLE  hMem;
  1576.     LPSTR   lpKeyBuf;
  1577.     int     nSize;
  1578.     char    szTmp[MAX_STRING_LENGTH];
  1579.  
  1580.     // this code taken from Unidrv.dll
  1581.     // read in all the key names under the old section
  1582.     nSize = KEY_BUF_SIZE_INC;
  1583.     if (!(hMem = GlobalAlloc(GHND, (long)nSize)))
  1584.         return FALSE;
  1585.     lpKeyBuf = GlobalLock(hMem);
  1586.  
  1587.     while (GetProfileString(lpOldSec, (LPSTR)NULL, "", lpKeyBuf, nSize)
  1588.            == nSize - 2)
  1589.     {
  1590.         // not enough buffer space for all the key names.
  1591.         GlobalUnlock(hMem);
  1592.         nSize += KEY_BUF_SIZE_INC;
  1593.         if (!(hMem = GlobalReAlloc(hMem, (long)nSize, GHND)))
  1594.             return FALSE;
  1595.         lpKeyBuf = GlobalLock(hMem);
  1596.     }
  1597.     // loop through each key and copy the value from the old to the new.
  1598.     while ((nSize = lstrlen(lpKeyBuf)) > 0)
  1599.     {
  1600.         //  filter out all keys starting with "softfont"
  1601.  
  1602.         lstrcpy((LPSTR)szTmp, lpKeyBuf);
  1603.         szTmp[8] = '\0';   //  Truncate after 8 chars
  1604.  
  1605.         if(lstrcmpi((LPSTR)"softfont", (LPSTR)szTmp))
  1606.         {
  1607.             GetProfileString(lpOldSec, lpKeyBuf, "", (LPSTR)szTmp, sizeof(szTmp));
  1608.             if(!WriteProfileString(lpNewSec, lpKeyBuf, (LPSTR)szTmp))
  1609.                 return(FALSE);
  1610.         }
  1611.         lpKeyBuf += (nSize + 1);
  1612.     }
  1613.     GlobalUnlock(hMem);
  1614.     GlobalFree(hMem);
  1615.     return(TRUE);
  1616. }
  1617.  
  1618. LPSTR  NEAR  PASCAL   Transfer(buffer1, lszPort)
  1619. LPSTR  buffer1, lszPort;
  1620. {
  1621.     //  this function copies the string from lszPort to buffer1
  1622.     //  and returns  a pointer to buffer1.  If lszPort is null
  1623.     //  nothing happens and lszPort  is returned.
  1624.  
  1625.     if(!lszPort)
  1626.         return(lszPort);
  1627.     lstrcpy(buffer1, lszPort);
  1628.     return(buffer1);
  1629. }
  1630.