home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / os2sdk / os2sdk12 / stock / print.doc < prev    next >
Encoding:
Internet Message Format  |  1990-06-07  |  34.4 KB

  1. From:    Ben Slivka
  2. Subj:    Printing Made Easy in OS/2 v1.21
  3. Date:    06-May-1990 - Initial version
  4.     23-May-1990 - Identify incomplete sections
  5.     07-Jun-1990 - Fill in sections on application printing
  6.  
  7. Contents
  8.  
  9.     1...........Overview - Printing Made Easy
  10.     1.1.........A Small Number of Choices
  11.     1.2.........The Printer Installer
  12.  
  13.     2...........How to Print from an Application
  14.     2.1.........Selecting a "printer"
  15.     2.2.........Managing Job Properties
  16.     2.3.........Opening a DC to Print
  17.     2.4.........Order of API calls
  18.  
  19.     3...........PM Printer Driver Guildelines
  20.     3.1.........DLL Usage
  21.     3.2.........Multi-file Driver Installation
  22.     3.3.........File Versioning
  23.  
  24. Appendicies
  25.     A...........Metafile Restrictions
  26.     B...........Application Printing API Order Sample Code
  27.     C...........Driver DLL Usage Sample Code
  28.  
  29. Glossary
  30.  
  31.  
  32. -----------
  33. 1. Overview
  34. -----------
  35.     The OS/2 printing environment is very complicated.    This complexity
  36. is a result of the many choices available at every turn to both application
  37. authors and printer driver authors.  This document eliminates this complexity
  38. by providing specific recommendations for all important printing operations.
  39.  
  40.     For application authors, this document reduces the complexity of printing
  41. by providing sample code that abstracts *printer devices* and *queues* into
  42. a single entity -- a *printer*.  This greatly simplifies the printing model
  43. for you, allowing you to focus on your application code.
  44.  
  45.     For driver authors, this document describes some simplifications in the
  46. printing environment, and addresses installation and DLL management.
  47.  
  48.     Here is a summary of the changes versus OS/2 v1.2:
  49.  
  50.     1)    The Print Manager (aka: Spooler) is always enabled.
  51.  
  52.     This reduces the testing burden for application and PM printer driver
  53.     authors, and ensures that all OS/2 applications can print on the same
  54.     system (if app A only worked with the Print Manager enabled, and app
  55.     B only worked with the Print Manager disabled, then a user would not
  56.     be able to print with both A and B!)
  57.  
  58.     2)    Setting up a Queue+Printer is strongly encouraged
  59.  
  60.     This reduces the number of testing scenarios for application authors.
  61.     The Printer Installer applet always creates a Queue+Printer, and
  62.     since this is so much easier than using the Control Panel and the
  63.     Print Manager, we expect most users will always have this
  64.     configuration.
  65.  
  66.     3)    PM_Q_STD is encouraged as the print job type.
  67.  
  68.     This improves the responsiveness of the application -- it prints
  69.     faster because the rendering is done by the Print Manager.  PM_Q_STD
  70.     has some restrictions on GPI calls, however, so it is not for all
  71.     applications.
  72.  
  73.  
  74. ------------------------------
  75. 1.1. A Small Number of Choices
  76. ------------------------------
  77.  
  78.     Printing from a PM application involves the following tasks:
  79.     1)  Selecting a printer
  80.     2)  Managing Job Properties
  81.     3)  Opening a printer DC
  82.     4)  Associating a PS with the DC
  83.     5)  Issuing GPI calls to print
  84.     6)  Ending or aborting a print job
  85.  
  86.     Tasks 1 through 3 are by far the most obscure in OS/2.  Section 2
  87.     below describes how to perform these tasks.  Sample code is provided
  88.     to illuminated the details.
  89.  
  90.  
  91. --------------------------
  92. 1.2. The Printer Installer
  93. --------------------------
  94.     OS/2 v1.21 introduces a new system application, the Printer Installer
  95. (PMPRINST.EXE).  The Printer Installer provides a simple, quick method
  96. of installing a printer driver and creating a Queue+Printer pair -- a task
  97. that previously required the expert use of both the Control Panel and the
  98. Print Manager.
  99.  
  100.     The Printer Installer performs the following operations that
  101. used to be the province of the Control Panel and the Print Manager:
  102.     a)    Install a printer driver
  103.     b)    Create a "printer"
  104.     c)    Create a "queue"
  105.     d)    Set Printer Properties
  106.     e)    Set Job Properties
  107.  
  108.     The Control Panel and Print Manager retain the ability to perform
  109. these operations separately, as this is necessary for setting up
  110. complicated configurations (like pooled printers).  However, the Printer
  111. Installer will satisfy the needs of most users.
  112.  
  113.  
  114.  
  115. -----------------------------------
  116. 2. How to Print from an Application
  117. -----------------------------------
  118.  
  119.     This section describes all the tasks a PM application must perform
  120. in order to print under PM.  These include:
  121.  
  122.     a.    Enumeratating all printers + default printer
  123.     b.    Choosing a printer
  124.     c.    Managing job properties
  125.     d.    Opening/Closing/Aborting a print job
  126.     e.    Printing multiple pages
  127.  
  128.     Other aspects of printing (coordinate transformations, font selection,
  129. etc.) are application-specific, and are not covered here.
  130.  
  131.     In the following sections, references to the sample code will be used
  132. to provide concrete instruction.
  133.  
  134.     NOTE: The printing functions in PRINT.C/PRINT.H are provided as
  135.       sample code.    You are free to modify this code and include it
  136.       in your application.
  137.  
  138.       You will likely have to modify the source code to support your
  139.       particular memory management strategy, but otherwise the code
  140.       should be usable as-is.
  141.  
  142.  
  143. --------------------------
  144. 2.1. Selecting a "printer"
  145. --------------------------
  146.  
  147.     The following functions in print.c are used to manage printers:
  148.  
  149.       HPRINTERLIST PrintCreatePrinterList(HAB hab);
  150.       HPRINTER       PrintQueryNextPrinter(HPRINTERLIST hprtlist,HPRINTER hprt);
  151.       HPRINTER       PrintQueryDefaultPrinter(HPRINTERLIST hprtlist);
  152.       ULONG       PrintQueryPrinterInfo(HPRINTER hprt,USHORT index);
  153.  
  154.     PrintCreatePrinterList
  155.     Get list of all printers in the system.
  156.  
  157.     PrintQueryNextPrinter
  158.     Walk through printer list.
  159.  
  160.     PrintQueryDefaultPrinter
  161.     Get default printer.
  162.  
  163.     PrintQueryPrinterInfo
  164.     Get information about a specific printer.
  165.  
  166.  
  167.     These functions are used by your user interface code to present the
  168. user with a list of possible printer destinations.  The default printer
  169. should be presented as the default choice.  The PrintQueryPrinterInfo API
  170. can be used to produce a nice name.
  171.  
  172. ----------------------------
  173. 2.2. Managing Job Properties
  174. ----------------------------
  175.  
  176.     Job Properties are printer driver/model-specific data (in a private
  177. data format that is particular to the driver) that describe modifiable
  178. properties for a print job.  For example, common job properties are
  179. orientation (Portrait vs. Landscape), print quality, and paper form.
  180.  
  181.     Your application should:
  182.     a)  Store job properties with each document
  183.     b)  Use stored job properties to select a target printer
  184.     c)  Use stored job properties on DevOpenDC
  185.     d)  Allow the user to change job properties on a per-document basis
  186.  
  187.     The following functions in print.c are used to manage printers:
  188.  
  189.       BOOL     PrintQueryJobProperties(HPRINTER hprt,USHORT *pcb,BYTE *pb);
  190.       BOOL     PrintChangeJobProperties(HPRINTER hprt);
  191.       VOID     PrintResetJobProperties(HPRINTER hprt);
  192.       HPRINTER PrintMatchPrinter(HPRINTERLIST hprtlist,USHORT cb,BYTE *pb);
  193.  
  194.     PrintQueryJobProperties
  195.     Query job property information from a printer.    This is in a form
  196.     suitable for storing with an application document file, and is
  197.     passed to PrintMatchPrinter when the document is opened in the
  198.     future.
  199.  
  200.     PrintChangeJobProperties
  201.     Let the user interact with the PM printer driver to inspect/modify
  202.     the job properties.
  203.  
  204.     PrintResetJobProperties
  205.     Reset the printer job properties (for the application, not the
  206.     system) to the default job properties for the printer.
  207.  
  208.     PrintMatchPrinter
  209.     Take job properties saved with a document (retrieved by
  210.     PrintQueryJobProperties in the first place) and find the printer
  211.     that most closely matches.  The match criteria are that the
  212.     driver name and model are identical, and the driver data size
  213.     is identical.  If no such match exists, NULL is returned, and you
  214.     should select the system default printer.
  215.  
  216.  
  217.     Your application should call PrintMatchPrinter when a document is
  218. opened which has job properties stored with it.  Your application user
  219. interface must provide a way to call PrintChangeJobProperties to let
  220. the user change the job properties.  Your application should store
  221. job properties with each document, but do so only if the users changes
  222. the job properties.  Optionally, your application may provide user
  223. interface to allow the user to reset the job properties to the system
  224. default for a selected printer.
  225.  
  226.     NOTE: All of these functions have *no* affect on the system default
  227.       job property settings.
  228.  
  229.  
  230. --------------------------
  231. 2.3. Opening a DC to Print
  232. --------------------------
  233.  
  234.     The PrintOpenDC function makes opening a DC very simple:
  235.  
  236.     HDC PrintOpenDC(HAB hab,HPRINTER hprt,char *pszDataType);
  237.  
  238.     The only choices you have a which printer (selected by the user)
  239. and the print job data type (PM_Q_STD or PM_Q_RAW).
  240.  
  241.     A PM_Q_RAW print job is a stream of raw printer commands:
  242.     Advantages:
  243.         +    All GPI commands are supported
  244.     Disadvantages:
  245.         -    Print job is usually larger than PM_Q_STD
  246.  
  247.     A PM_Q_STD print job is a stream of recorded GPI calls (called a metafile):
  248.     Advantages:
  249.         +    Print job is usually smaller than PM_Q_RAW
  250.         +    Application "finishes" printing sooner, since
  251.         translation of GPI to PDL is done after application has
  252.         spooled the metafile.
  253.     Disadvantages:
  254.         -    Not all GPI calls are supported (see Appendix A -- Metafile
  255.         Restrictions).
  256.  
  257.     If your application can live within the Metafile restrictions, you should
  258. always create PM_Q_STD print jobs.  If your application cannot live within
  259. these restrictions, PM_Q_RAW is fine.
  260.  
  261.  
  262. -----------------------
  263. 2.4. Order of API calls
  264. -----------------------
  265.     A)    A well-behaved OS/2 v1.21 printing application will print a
  266.     document in the following manner:
  267.  
  268.      1. DevOpenDC()
  269.      2. GpiAssociate/Create/SetPS()
  270.      3. DevEscape(STARTDOC)
  271.      4. <drawing commands>
  272.      5. DevEscape(NEWFRAME) \==> Repeated 0 or more times
  273.      6. <drawing commands>    /
  274.      7. DevEscape(ENDDOC)
  275.      8. GpiAssociate(hPS,NULL)
  276.      9. GpiDestroyPS(hPS)
  277.     10. DevCloseDC();
  278.  
  279.     NOTE: DevEscape(ENDDOC) performs an *implicit* NEWFRAME.  If you
  280.           include a NEWFRAME just before the ENDDOC, you will get an
  281.           extra (blank) page of output.
  282.  
  283.     B)    DevEscape(ABORTDOC) is allowed anytime between a STARTDOC and
  284.     ENDDOC.  The ABORTDOC causes the driver to throw away any
  285.     buffered information, and behaves otherwise like an ENDDOC.
  286.  
  287.     C)    The following chart documents the valid API calling order,
  288.     assuming the DC is already open:
  289.  
  290.         Last call made
  291.         Allowed calls
  292.         -----------------------------
  293.         DevOpenDC
  294.         GpiAssociate/Set/CreatePS
  295.         CloseDC
  296.  
  297.         GpiAssociate/Set/CreatePS
  298.         GpiAssociate/Set/CreatePS
  299.         STARTDOC
  300.         CloseDC
  301.  
  302.         STARTDOC, NEWFRAME, drawing
  303.         NEWFRAME
  304.         drawing
  305.         ENDDOC
  306.         ABORTDOC
  307.  
  308.         ENDDOC, ABORTDOC
  309.         GpiAssociate/Set/CreatePS
  310.         STARTDOC
  311.         CloseDC
  312.  
  313.     Query calls on the DC and PS are always allowed, assuming the
  314.     DC and PS exist.
  315.  
  316.     D)    Details on NEWFRAME
  317.  
  318.     NEWFRAME is a page separator.  It signals that a page is complete,
  319.     and another page is starting.  The following pseudocode describes
  320.     how PM processes STARTDOC/NEWFRAME/ENDDOC:
  321.  
  322.         STARTDOC
  323.         do initialization stuff;
  324.         SetUpForPage();
  325.  
  326.         NEWFRAME
  327.         CloseCurrentPage();    // Form feed
  328.         SetUpForPage();
  329.  
  330.         ENDDOC
  331.         CloseCurrentPage();    // Form feed
  332.         do cleanup stuff;
  333.  
  334.  
  335.  
  336. --------------------------------
  337. 3. PM Printer Driver Guildelines
  338. --------------------------------
  339.  
  340.     This section describes new conventions for OS/2 v1.21 PM printer
  341. drivers.  These conventions allow OS/2 to correctly install a PM printer
  342. driver, and ensure that the driver functions correctly.
  343.  
  344. Key Points
  345. ----------
  346.     a)    All files associated with a particular printer driver are
  347.     copied to a directory subtree (section 1).
  348.     b)    Printer driver files are not necessarily in LIBPATH (section 1).
  349.     c)    A printer driver must be careful about private DLL usage in
  350.     response to the DevQueryDeviceName API (section 4).
  351.     d)    EAs should be used for multi-file drivers (section 2).
  352.     e)    EAs should be used to indicate driver file version (section 3).
  353.  
  354.  
  355.     The OS/2 v1.21 Printer Installer (PMPRINST.EXE) is an application that
  356.     installs printer drivers and creates printers and queues.  It is
  357.     intended for use in place of the Control Panel and Print Manager for
  358.     these purposes, as it requires only half as many operations, and
  359.     requires no guessing on the part of the user.
  360.  
  361.     In addition to making printer configuration simpler, the Printer
  362.     Installer also solves two install problems: 1) multi-file driver
  363.     installation, and 2) driver file versioning.
  364.  
  365.     In order to successfully update multi-file printer drivers, such
  366.     printer drivers must be careful about how they load their (private)
  367.     DLLs.
  368.  
  369.     PMPRINST copies all files for a single driver into either a single
  370.     directory, or into a directory subtree (depends upon EA settings
  371.     on the driver files).  In either case, any DLLs that are copied are
  372.     most probably not in a directory in LIBPATH.
  373.  
  374.     Each driver is installed in a different directory.
  375.  
  376.     Hence, a correctly written driver may only assume that all of its
  377.     files are in a single directory (or directory subtree).  See the
  378.     LoadDriverDLL(...) function in section 4 below for sample code used
  379.     to get the fully qualified path of a DRV/DLL.
  380.  
  381.  
  382.  
  383. --------------
  384. 3.1. DLL Usage
  385. --------------
  386.  
  387.     In order to show the user a nice list of printers to be installed,
  388.     PMPRINST calls DevQueryDeviceNames (DQDN) on a driver to get all the
  389.     model names and descriptions that the driver supports.
  390.  
  391.     If (an older version of) the driver is not installed, this works just fine.  However,
  392.     *if* the driver is installed, *and* it has supporting DLLs, *and* the
  393.     driver is not *careful* about how it loads its supporting DLLs in
  394.     response to the DQDN call, *then* PMPRINST will not be able to update the
  395.     supporting DLLs.
  396.  
  397.     In order for PMPRINST to be able to update a printer driver, the driver
  398.     must adhere to one of these rules:
  399.  
  400.     1)    Do not use *any* supporting DLLs on the DQDN call.
  401. -or-
  402.     2)    If a supporting DLL *is* used, it should be loaded from the
  403.     exact same directory that the .DRV file was loaded from.  The
  404.     code fragment below can be used to implement this logic.
  405.  
  406.     Once the DLL has served its purpose, the driver should call
  407.     DosFreeModule to unload the DLL.
  408.  
  409.     If one of these rules if not followed, PMPRINST will cause a supporting
  410.     DLL to be opened, PMPRINST will have no way of unloading it, and hence
  411.     PMPRINST will not be able to replace the DLL.
  412.  
  413.     If you choose to follow rule 2, you should verify (during testing)
  414.     that DosFreeModule did its job by calling it again and checking that
  415.     you get the error ERROR_MOD_NOT_FOUND.
  416.  
  417.  
  418.  
  419. -----------------------------------
  420. 3.2. Multi-file Driver Installation
  421. -----------------------------------
  422.     A multi-file driver consists of a .DRV file and one or more supporting
  423.     files.  These files are commonly DLLs, fonts, or help files, but may
  424.     contain anything.
  425.  
  426.     PMPRINST addresses the following problems:
  427.     1)  The PM Control Panel only copies the .DRV file.  It has no
  428.         way to determine what other files are needed.
  429.     2)  There is no way for multiple printer drivers to share
  430.         common files.
  431.     3)  There is no automatic way to avoid name collisions between
  432.         files from different vendors.
  433.  
  434.     PMPRINST introduces eight EAs for .DRV files to solve these problems.
  435.     The solutions to the above problems are as follows:
  436.  
  437.     1)  Add EAs to the .DRV file to describe all required (and optional)
  438.         files.
  439.  
  440.     2)  Allow the .DRV file (via EAs) to describe a three-level
  441.         directory hierarchy to support file sharing.
  442.  
  443.     3)  Use directory hierarchy to avoid name collisions.
  444.  
  445.     Here are the EAs that PMPRINST supports for multi-file drivers:
  446.  
  447.     EA name
  448.         EA contents
  449.     ----------------------------------------------------------------
  450.     VendorName
  451.         ASCIIZ string; must be a valid 8.3 FAT file name.
  452.         Ignored if ClassName EA is not present.
  453.  
  454.         This name is used for the "vendor directory".  The
  455.         vendor directory contains vendor-specific files and the
  456.         "class directory".
  457.  
  458.         Files should be placed in this directory only if they are
  459.         common across all printers made by a particular vendor,
  460.         both now and in the future.
  461.  
  462.         It is more common that this directory will be empty (except
  463.         for containing the "class directory"), since it's primary
  464.         purpose is to ensure name uniqueness of class names across
  465.         vendors.
  466.  
  467.     ClassName
  468.         ASCIIZ string; must be a valid 8.3 FAT file name.
  469.         Ignored if VendorName EA is not present.
  470.  
  471.         This name is used for the "class directory".  The
  472.         class directory contains class-specific files and the
  473.         "driver directory".
  474.  
  475.         Files should be placed in this directory only if they are
  476.         common across all printers of a particular class made by
  477.         the vendor.  An example would be font files that are supported
  478.         by several printers that have a different page description
  479.         language, and hence have different drivers.
  480.  
  481.     RequiredVendorFiles
  482.     RequiredClassFiles
  483.     RequiredDriverFiles
  484.         ASCIIZ string; list of required files, separated
  485.         by commas.    All valid file name characters, including
  486.         blanks, are significant (except for commas, which
  487.         are always treated as file name separators).
  488.         The file names should be limited to valid 8.3 FAT names.
  489.         Wild cards are supported, and follow the semantics of OS/2.
  490.  
  491.         PMPRINST looks for these files in the same source directory
  492.         as the .DRV file, and then copies them to the target disk.
  493.  
  494.         PMPRINST will *fail* to install the driver if it cannot
  495.         successfully copy all specified files to the target disk.
  496.  
  497.     OptionalVendorFiles
  498.     OptionalClassFiles
  499.     OptionalDriverFiles
  500.         Same format as the RequiredXxxFiles EAs.
  501.  
  502.         PMPRINST looks for these files in the same source directory
  503.         as the .DRV file, and then copies them to the target disk.
  504.  
  505.         PMPRINST will successfully install the driver regardless of
  506.         whether or not these files are found and copied.
  507.  
  508.     NOTE: These EAs should be marked as "need" EAs (see EA.EXE description
  509.       below), to tell OS/2 v1.2 that the EAs are important.  This does
  510.       not guarantee that the EAs will remain with the file (you could
  511.       copy the file under DOS, and the EAs would be lost), but it
  512.       reduces the chances under OS/2.
  513.  
  514.     These EAs are used to list the files the driver needs and wants,
  515.     and to describe where they are installed on the target disk.  The
  516.     following examples show the two cases.  In both cases, a root path
  517.     is used as the starting point.  These examples will show c:\os2\dll
  518.     as the root path.  The driver *may not* assume that location,
  519.     however, as it may change in future releases of OS/2:
  520.  
  521.     Case 1: Driver *without* VendorName/ClassName EAs
  522.  
  523.     This is the simple case.  A new directory is created on the
  524.     target disk, and all files for the driver are copied to that
  525.     directory.
  526.  
  527.     Source location is A:\
  528.         a:\speedy.drv
  529.         RequiredDriverFiles=render.dll
  530.         OptionalDriverFiles=*.fnt
  531.         a:\render.dll
  532.         a:\square.fnt
  533.         a:\rounded.fnt
  534.  
  535.     Target is C:\OS2\DLL
  536.         c:\os2\dll\speedy\speedy.drv
  537.         c:\os2\dll\speedy\render.dll
  538.         c:\os2\dll\speedy\square.fnt
  539.         c:\os2\dll\speedy\rounded.fnt
  540.  
  541.     Case 2: Driver *with* VendorName/ClassName EAs
  542.  
  543.     Source location is A:\
  544.         a:\tpc1000.drv
  545.         VendorName=TPC
  546.         ClassName=OUTLINE
  547.         RequiredVendorFiles=help.dll
  548.         OptionalVendorFiles=*.hlp
  549.         RequiredClassFiles=font.dll
  550.         OptionalClassFiles=*.fnt
  551.         RequiredDriverFiles=render.dll
  552.         OptionalDriverFiles=*.crt
  553.         a:\help.dll
  554.         a:\tpc.hlp
  555.         a:\font.dll
  556.         a:\smooth.fnt
  557.         a:\render.dll
  558.         a:\tpcA.crt
  559.  
  560.     Target is C:\OS2\DLL
  561.         c:\os2\dll\tpc\outline\tpc1000\tpc1000.drv
  562.         c:\os2\dll\tpc\outline\tpc1000\render.dll
  563.         c:\os2\dll\tpc\outline\tpc1000\tpcA.crt
  564.         c:\os2\dll\tpc\outline\font.dll
  565.         c:\os2\dll\tpc\outline\smooth.fnt
  566.         c:\os2\dll\tpc\help.dll
  567.         c:\os2\dll\tpc\tpc.hlp
  568.  
  569.     NOTES:
  570.     1)  To find its Required/OptionalDriverFiles, a driver must
  571.         look in the directory containing the .DRV file.  See section
  572.         4 -- Use of DLLs by Printer Drivers -- for details on how
  573.         to determine this path.
  574.  
  575.     2)  To find its Required/OptionalClassFiles, a driver must
  576.         look in the directory one level up from the directory containing
  577.         the .DRV file.  Be sure to use FindLastPathSeparator function
  578.         (see code in section 4) in order to well-behaved on DBCS systems.
  579.  
  580.     3)  To find its Required/OptionalVendorFiles, a driver must
  581.         look in the directory twoe levels up from the directory containing
  582.         the .DRV file.  Be sure to use FindLastPathSeparator function
  583.         (see code in section 4) in order to well-behaved on DBCS systems.
  584.         the drivers under the same VendorName.
  585.  
  586.   ---------------------------------------------------------------------------
  587.  
  588.     Use the EA.EXE tool to manipulate these EAs:
  589.  
  590.     usage: ea -? | [-s[n] name=value | -d name] file
  591.        This program manipulates text-valued EAs.
  592.            -s  : Set EA.
  593.            -sn : Set 'need' EA.
  594.            -d  : Delete EA.
  595.            -?  : Show this help information.
  596.      Otherwise : Display all EAs.
  597.  
  598.      Examples:
  599.        ea file.dat
  600.        ea -s  'my pie'='apple and cherry' file.dat
  601.        ea -s  language="french german"    file.dat
  602.        ea -s  language=french          file.dat
  603.        ea -sn needEA='important value'    file.dat
  604.        ea -d  language              file.dat
  605.  
  606.      NOTES: 1) Wild cards are supported in the file name.
  607.         2) 'Need' EAs are displayed with a preceeding '*'.
  608.  
  609.     To set the EAs for the two examples above:
  610.  
  611.     ea -sn RequiredDriverFiles=render.dll     speedy.drv
  612.     ea -sn OptionalDriverFiles=*.fnt     speedy.drv
  613.  
  614.     ea -sn VendorName=TPC             tpc1000.drv
  615.     ea -sn ClassName=OUTLINE         tpc1000.drv
  616.     ea -sn RequiredVendorFiles=help.dll     tpc1000.drv
  617.     ea -sn OptionalVendorFiles=*.hlp     tpc1000.drv
  618.     ea -sn RequiredClassFiles=font.dll     tpc1000.drv
  619.     ea -sn OptionalClassFiles=*.fnt         tpc1000.drv
  620.     ea -sn RequiredDriverFiles=render.dll     tpc1000.drv
  621.     ea -sn OptionalDriverFiles=*.crt     tpc1000.drv
  622.  
  623.  
  624.  
  625. --------------------
  626. 3.3. File Versioning
  627. --------------------
  628.  
  629.     OS/2 users will encounter situations where they want to install
  630.     a "new" version of a printer driver that is already installed.
  631.  
  632.     This will occur for two reasons:
  633.     1)    There will be many methods of printer driver distribution
  634.     (with OS/2 itself, with applications, on electronic bulletin
  635.     boards, etc.).
  636.     2)    Printer drivers will be enhanced and new version released.
  637.  
  638.     The problem arises when a user installs what she *thinks* is a newer
  639.     version, but it is not a newer version.
  640.  
  641.     PMPRINST solves this problem by respecting the .VERSION EA on all printer
  642.     driver files.
  643.  
  644.     ALL DRIVER AUTHORS ARE STRONGLY ENCOURAGED TO SET .VERSION EAs, and
  645.     INCREMENT THE VERSION NUMBER WITH EACH PUBLIC RELEASE.
  646.  
  647.     There is no explicit convention for the format of the .VERSION EA,
  648.     so PMPRINST introduces one.  A valid .VERSION EA value is a base-36
  649.     number in the range 000.000 to ZZZ.ZZZ.  There can be at most three
  650.     digits on the left of the decimal point and at most three digits on
  651.     the right of the decimal point.  Digits may be any letter (case is
  652.     ignored) or 0..9 (hence base 36).  The order of the digits is 0..9
  653.     followed by A..Z.
  654.  
  655.     Here is a slightly more formal definition of the format:
  656.  
  657.     digit     ::= 0..9 A..Z     // a..z == A..Z (case-insensitive)
  658.     3digits     ::= digit | digit digit | digit digit digit
  659.     majorver ::= 3digits
  660.     minorver ::= 3digits
  661.     version     ::= majorver [. minorver]
  662.  
  663.     Here are some representative versions, sorted in increasing order:
  664.  
  665.       0.0
  666.       0.001
  667.       0.ZZZ
  668.       1.000
  669.       1.00b
  670.       9.0
  671.       A.Z
  672.      22.0
  673.      23.0
  674.     22B.0
  675.  
  676.     A common practice is to use letter suffixes to indicate a minor release.
  677.  
  678.     When installing a driver, the following table describes how PMPRINST
  679.     behaves in the case where a driver file already exists:
  680.  
  681.     Old file    New file  Action
  682.     --------    --------  ------
  683.     no EA        no EA      Ask user if new file should replace old file
  684.     no EA        EA      Copy new file
  685.     EA less than    EA      Copy new file
  686.     EA        no EA      Do nothing (leave old file alone)
  687.     EA equal to    EA      Do nothing (leave old file alone)
  688.     EA greater than EA      Do nothing (leave old file alone)
  689.  
  690.     Please use the EA.EXE tool to set driver file version numbers.
  691.     For example:
  692.  
  693.     ea -sn .version=2.03a EPSONDAT.DLL
  694.     ea -sn .version=2.03a EPSON.HLP
  695.     ea -sn .version=2.03a EPSON.DRV
  696.  
  697.     NOTE: This EA should be marked as a "need" EA, to improve the chances
  698.       that it will stay with the file.  [See comments on the multi-file
  699.       driver EAs in Section 3.2 above.]
  700.  
  701.     EA.EXE supports wild-cards, so
  702.  
  703.     ea -sn .version=2.03a EPSON*.*
  704.  
  705.     would have the same effect (if the three files above were the only
  706.     files that matched the pattern EPSON*.*)
  707.  
  708.  
  709.  
  710. ***********
  711. APPENDICIES
  712. ***********
  713.  
  714. ------------------------
  715. A. Metafile Restrictions
  716. ------------------------
  717.  
  718. A metafile can record most -- BUT NOT ALL -- DEV/GPI calls.  If an
  719. application can avoid making the non-recorded calls, then it can
  720. use PM_Q_STD on the DevOpenDC call.  This tells OS/2 to spool a
  721. metafile for printing, as opposed to raw printer commands.
  722.  
  723. The advantages of printing using PM_Q_STD (as opposed to PM_Q_RAW) is
  724. that the (often time-consuming) translation of GPI to raw printer
  725. commands (e.g., PostScript, PCL) is done in the context of the
  726. Print Manager (aka: the spooler), and hence an application is "done"
  727. printing sooner, thus allowing a user to proceed with useful work.
  728.  
  729. It is strongly recommended that an application use PM_Q_STD.
  730.  
  731. PM_Q_RAW is supported, but an application should print with PM_Q_RAW
  732. only if it cannot live withing the metafile restrictions.  In this case,
  733. the GPI translation to raw printer commands is done in the context of the
  734. application, causing the application to take longer to print and resulting
  735. (generally) in a larger spool file.
  736.  
  737. The text that followes was copied from:
  738.  
  739.    Programming Reference
  740.    MS Operating System/2 Version 1.2
  741.    Technical Reference: Volume 3
  742.    November, 1989
  743.  
  744.  
  745.    This     section  lists     some  general rules  that  must be  followed  when
  746.    creating  a    metafile  that     is  to     be  acceptable     to  SAA-conforming
  747.    implementations, or    replayed  into    a  presentation     space    that  is in
  748.    'draw-and-retain' or 'retain'mode   (see GpiSetDrawingMode).
  749.  
  750.    *   These  items  must be  established or defaulted    before    any drawing
  751.        occurs to the graphics presentation space:
  752.  
  753.        -   The graphics field (GpiSetGraphicsField).  For an SAA-conforming
  754.        metafile, the  graphics field  must    be defaulted or     set to     no
  755.        clipping.
  756.        -   The code page for the default character set (GpiSetCp).
  757.        -   The color table (GpiCreateLogColorTable).  The size of the color
  758.        table must not exceed 31KB.
  759.        -   the default viewing transform (GpiSetDefaultViewMatrix).
  760.        -   The     setting   of  the   draw   controls   (GpiSetDrawControl).
  761.        DCTL_DISPLAY must be defaulted or set on.
  762.        -   The    default values of attributes (see  GpiSetDefAttrs), viewing
  763.        limits  (see      GpiSetDefViewingLimits),   primitive     tag   (see
  764.        GpiSetDefTag) and arc parameters (see GpiSetDefArcParams).
  765.  
  766.        These  items must not be changed while the  metafile context remains
  767.        open.
  768.  
  769.    *   These calls must not be used:
  770.  
  771.        -   GpiBitBlt
  772.        -   GpiDeleteSetId  (note  that this means  that     local    identifiers
  773.        cannot be used again within the picture)
  774.        -   GpiErase
  775.        -   GpiExcludeClipRectangle
  776.        -   GpiIntersectClipRectangle
  777.        -   GpiOffsetClipRegion
  778.        -   GpiPaintRegion
  779.        -   GpiResetPS
  780.        -   GpiSetClipRegion
  781.        -   GpiSetPel
  782.        -   GpiSetPS
  783.        -   DevEscape (for an escape which is metafiled).
  784.  
  785.    *   The metafile context must not be reassociated.
  786.  
  787.    *   If a bit map is used as the source of a GpiWCBitBlt operation, or as
  788.        an area-fill pattern, it must not be modified.
  789.  
  790.    *   Only these foreground mixes must be used (see GpiSetMix):
  791.  
  792.        -   FM_DEFAULT
  793.        -   FM_OR
  794.        -   FM_OVERPAINT
  795.        -   FM_LEAVEALONE.
  796.  
  797.    *   Only these background mixes must be used (see GpiSetBackMix):
  798.  
  799.        -   BM_DEFAULT
  800.        -   BM_OVERPAINT
  801.        -   BM_LEAVEALONE.
  802.  
  803.    PROGRAMMING NOTE.
  804.     There is no  restriction concerning the use of primitives outside
  805.     segments.  These are metafiled in segment(s) with zero identifier.
  806.  
  807. SUPPORTED Metafile DevEsc commands:
  808.     DEVESC_QUERYESCSUPPORT
  809.     DEVESC_GETSCALINGFACTOR
  810.     DEVESC_STARTDOC
  811.     DEVESC_ENDDOC
  812.     DEVESC_NEXTBAND
  813.     DEVESC_ABORTDOC
  814.     DEVESC_NEWFRAME
  815.     DEVESC_DRAFTMODE
  816.     DEVESC_FLUSHOUTPUT
  817.     DEVESC_RAWDATA
  818.     DEVESC_QUERYVIOCELLSIZES
  819.     DEVESC_BREAK_EXTRA
  820.     DEVESC_CHAR_EXTRA
  821.  
  822. UNSUPPORTED Metafile DevEsc commands:
  823.     DEVESC_GETCP
  824.     DEVESC_SETMODE
  825.     DEVESC_DBE_FIRST
  826.     DEVESC_DBE_LAST
  827.     DEVESC_STD_JOURNAL
  828.  
  829.  
  830. ---------------------------------------------
  831. B. Application Printing API Order Sample Code
  832. ---------------------------------------------
  833.  
  834. *** MAY BE OBSOLETE ***
  835.  
  836. {
  837. // open printer DC
  838. if((hdc = GetPrintDC(hab, OD_QUEUED, PrinterSelected)) != NULL) {
  839.  
  840.     // create printer PS, use selected mapping mode
  841.     hps = GpiCreatePS(hab,hdc,&sl,idMode|GPIA_ASSOC|GPIF_DEFAULT|GPIT_NORMAL);
  842.     if(hps != NULL) {
  843.     // Start document
  844.     pszJob = "Test print job";
  845.     DevEscape(hdc,DEVESC_STARTDOC,(LONG)strlen(pszJob),pszJob",0L,NULL);
  846.  
  847.     // Print each page
  848.     do {
  849.       cPages--;
  850.  
  851.       // Band, if banding device and desired
  852.       DevQueryCaps( hdc, CAPS_RASTER_CAPS, 1L, &lItem );
  853.       if (lItem & CAPS_RASTER_BANDING) {
  854.         ...
  855.         do {
  856.           DevEscape( hdc, DEVESC_NEXTBAND, NULL, NULL, &cBand, &rcBand );
  857.           // Output into each band.  Set flag when last band is done
  858.           ...
  859.         } while (!fLastBand); // Loop through each band until empty band
  860.  
  861.       } else // Not banding, just oputput
  862.           // Output entire page. Could merge in with banding logic
  863.  
  864.       // Only issue NEWFRAME *between* pages
  865.       if (cPages > 1)
  866.           DevEscape(hdc,DEVESC_NEWFRAME,0L,NULL,0L,NULL);
  867.     } while( cPages > 0 );
  868.  
  869.     // Should ENDDOC go here, or after unassociation?!?!?
  870.     DevEscape(hdc,DEVESC_ENDDOC,0L,NULL,0L,NULL);
  871.  
  872.     // Cleanup resource usage
  873.     GpiAssociate(hps,NULL);
  874.     GpiDestroyPS(hps);
  875.     }
  876.     // Cleanup resource usage
  877.     DevCloseDC(hdc);
  878.  
  879. }
  880.  
  881.  
  882.  
  883. -------------------------------
  884. C. Driver DLL Usage Sample Code
  885. -------------------------------
  886.  
  887.  
  888. #define INCL_DOSMODULEMGR        // Get module APIs
  889. #define INCL_WINCOUNTRY            // Get WinNextChar
  890. #include <os2.h>
  891.  
  892. #include <string.h>
  893.  
  894. main()
  895. {
  896.     HMODULE hmod;
  897.  
  898.     hmod = LoadDriverDLL("LASERJET.DRV","GENERIC.DLL");
  899.     if (hmod != 0)
  900.     // success, do DosGetProcAddr
  901.     else
  902.     // failure, could not find DLL
  903. }
  904.  
  905. char achPath[CCHMAX];            // Works with SS != DS memory model
  906.  
  907. /***    LoadDriverDLL - load DLL for printer driver
  908.  *
  909.  *    Entry
  910.  *        pszDriver - file name of driver (laserjet.drv)
  911.  *        pszDLL - file name of DLL (generic.dll)
  912.  *
  913.  *    Exit-Success
  914.  *        returns non-NULL HMODULE
  915.  *
  916.  *    Exit-Failure
  917.  *        returns NULL
  918.  *
  919.  *    Uses
  920.  *        achPath
  921.  *
  922.  *    Pseudo-Code
  923.  *        Get path where foo.drv came from;
  924.  *        Build full path for DLL;
  925.  *        Try loading full path;
  926.  *        Try loading from LIBPATH;
  927.  */
  928. HMODULE LoadDriverDLL(char *pszDriver,char *pszDLL)
  929. {
  930.     HMODULE    hmod;
  931.     char *    pchLast;
  932.  
  933.     // Get path of this driver
  934.  
  935.     if (!DosGetModHandle(pszDriver,&hmod))  // Should never fail!
  936.     return NULL;
  937.     if (!DosGetModName(hmod,sizeof(achPath),achPath)) // Should never fail!
  938.     return NULL
  939.  
  940.     //    Delete driver name from path
  941.  
  942.     pchLast = FindLastPathSeparator(achPath); // pchLast -> "\foo.drv"
  943.     pchLast++;                // pchLast -> "foo.drv"
  944.     *pchLast = '\0';            // Trim off "foo.drv" for load module
  945.                     // pch -> "c:\one\two\"
  946.  
  947.     // NOTE: achPath now holds the path of the directory containing the
  948.     //         *.DRV file.
  949.  
  950.     // Build fully-qualified path for DLL
  951.     strcat(achPath,pszDLL);        // achPath = "c:\one\two\foo.dll"
  952.  
  953.     // Try loading module
  954.     if (DosLoadModule(NULL,0,achPath,&hmod) // Try loading from same dir
  955.     return hmod;            // Found it
  956.  
  957.     if (DosLoadModule(NULL,0,pszDLL,&hmod) // Try loading from LIBPATH
  958.     return hmod;            // Found it
  959.     else
  960.     return NULL;            // Did not find it
  961. }
  962.  
  963.  
  964. /***    FindLastPathSeparator - find last path separator in a string
  965.  *
  966.  *    This routine is well-behaved for DBCS systems.
  967.  *
  968.  *    Entry
  969.  *        psz - string to search
  970.  *
  971.  *    Exit-Success
  972.  *        returns pointer to last path separator
  973.  *
  974.  *    Exit-Failure
  975.  *        returns NULL
  976.  */
  977. char *FindLastPathSeparator(char *psz)
  978. {
  979.     char *  pch;
  980.     char *  pchLast=NULL;
  981.  
  982.     pch = psz;
  983.     while (*pch != '\0') {
  984.     if ((*pch == '/') || (*pch == '\\'))
  985.         pchLast = pch;        // Save location of separator
  986.     pch = (char *)(USHORT)(ULONG)WinNextChar(hab,0,0,pch);
  987.     }
  988.     return pchLast;
  989. }
  990.  
  991.  
  992. ********
  993. GLOSSARY
  994. ********
  995.  
  996. Logical Printer
  997.     Associates a Printer Driver with a Port.
  998.     The Printer Installer creates one of these in the process of
  999.     creating a Printer. A Logical Printer can be manipulated via the
  1000.     "Setup Printers..." menu in the Print Manager.
  1001.  
  1002. Logical Queue
  1003.     Associates queuing (job spooling, priority scheduling, etc.)
  1004.     with one or more Logical Printers.
  1005.     The Printer Installer creates one of these in the process of
  1006.     creating a Printer. A Logical Printer can be manipulated via the
  1007.     "Setup Queues..." menu in the Print Manager.
  1008.  
  1009. Metafile
  1010.     A *partial* recording of GPI calls.  See Appendix A for Metafile
  1011.     Restrictions.
  1012.  
  1013. PDL
  1014. Page Description Language
  1015.     Native printer commands.
  1016.     Examples are Adobe's PostScript and Hewlett-Packard's Page Control
  1017.     Language (HP-PCL or PCL).
  1018.  
  1019. Physical Printer
  1020.     An actual printer, e.g., an HP LaserJet II, or an Apple Laserwriter.
  1021.  
  1022. Port
  1023.     Destination for a PDL byte stream.
  1024.     Examples are LPT1, LPT2, COM1, etc.
  1025.  
  1026. Printer
  1027.     Another name for a Logical Queue.
  1028.     This term is used in this document to enforce the notion (for
  1029.     applications) that Logical Printers and Logical Queues are not
  1030.     of interest to applications (as they certainly are of little
  1031.     interest to most users).
  1032.  
  1033. Printer Driver
  1034.     A DLL that translates GPI drawing commands into a specific PDL.
  1035.     Examples are LASERJET.DRV, PSCRIPT.DRV, IBM4201.DRV.
  1036.  
  1037. <end of document>
  1038.