home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / datafiles / text / c_manual / devices / printerdevice / printerdevice.doc < prev    next >
Text File  |  1995-02-27  |  56KB  |  1,620 lines

  1. 9    PRINTER DEVICE
  2.  
  3. 9.1  INTRODUCTION
  4.  
  5. The printer device works close together with both the serial
  6. and the parallel device. If you want to control a printer,
  7. there are several advantages of using the printer device
  8. instead of the serial or parallel device.
  9.  
  10. First you do not need to know to which port (serial or
  11. parallel) the printer is connected to. The printer device will
  12. simply look at the "Preferences" settings, and will there find
  13. this type of information.
  14.  
  15. Secondly, since the user has specified what type of printer
  16. is used with Preferences, the printer device will also know how
  17. to translate the universal printer commands (listed below) into
  18. that printers own special commands. This is very good since if
  19. your program can handle some of the commands listed below, it
  20. will work on most printers.
  21.  
  22. Finally, there exist a lot of special features like printing
  23. graphics, translating foreign characters, and changing the
  24. printer settings. All this is supported by the printer device.
  25.  
  26.  
  27.  
  28. 9.2  PRINTER DEVICE
  29.  
  30. The printer device is, as said above, very close connected to
  31. the serial and parallel devices. The printer device can be said
  32. to be on a "higher level". The reason of this is that the
  33. printer device will with help of Preferences control either
  34. the serial or parallel device. (See illustration "Printer
  35. Device".)
  36.  
  37.           ----------------
  38.           |Printer Device|
  39.           ----------------
  40.                   |
  41.                   V
  42.             -------------
  43.             |Preferences|
  44.             -------------
  45.              |         |
  46.              V         V
  47.   ---------------   -----------------
  48.   |Serial Device|   |Parallel Device|
  49.   ---------------   -----------------
  50.          |                  |
  51.          V                  V
  52.    -------------     ---------------
  53.    |Serial Port|     |Parallel Port|
  54.    -------------     ---------------
  55.  
  56.  
  57. Although the complexity of printing, the printer device is very
  58. easy and straight forward to use. It works like all other
  59. normal devices, and with only some extra structures and
  60. commands a lot can be done.
  61.  
  62.  
  63.  
  64. 9.2.1  THE PRINTER DEVICE'S REQUESTBLOCKS
  65.  
  66. As with all devices you use a request block to communicate with
  67. the printer device. You initialize the request block as will be
  68. described below, and then you simply send it to the device with
  69. for example an DoIO() or SendIO() command.
  70.  
  71. Since the printer device can handle a lot of special commands
  72. there exist three different request blocks. Which should be
  73. used depends on what you want to do.
  74.  
  75.   1. The standard request block (struct IOStdReq) should be
  76.      used for all "normal" commands.
  77.  
  78.   2. The special printer command block (struct IOPrtCmdReq)
  79.      should be used when you want to send special commands to
  80.      the printer.
  81.  
  82.   3. The special graphic request block (struct IODRPReq) should
  83.      be used when you want to print graphics (dump a Rastport
  84.      to a printer).
  85.  
  86. To make it easier for you the printer device can handle a union
  87. with these three structures. This means that you only have to
  88. bother about one singe request block. The union look like this:
  89.  
  90. union printerIO
  91. {
  92.   struct IOStdReq ios;
  93.   struct IODRPReq iodrp;
  94.   struct IOPrtCmdReq iopc;
  95. };
  96.  
  97. Each structure of this union will be described in more detail
  98. below.
  99.  
  100.  
  101.  
  102. 92.2.1.1  STANDARD REQUEST BLOCK
  103.  
  104. The printer device use a standard request block (struct
  105. IOStdReq) for all normal commands. It looks like this: (Defined
  106. in header file "exec/io.h". Note that you will probably only
  107. use some of these fields, so you do not need to bother too
  108. much about it.)
  109.  
  110. struct IOStdReq
  111. {
  112.   struct Message io_Message;
  113.   struct Device  *io_Device;
  114.   struct Unit    *io_Unit;
  115.   UWORD  io_Command;
  116.   UBYTE  io_Flags;
  117.   BYTE   io_Error;
  118.   ULONG  io_Actual;
  119.   ULONG  io_Length;
  120.   APTR   io_Data;
  121.   ULONG  io_Offset;
  122. };
  123.  
  124. io_Message: This is the message that will be sent to your reply
  125.             port once the device has successfully or not
  126.             finished your request
  127.  
  128. io_Device:  Pointer to the device which is using this request
  129.             block.
  130.  
  131. io_Unit:    If the device has several units (like the Trackdisk
  132.             Device) this is a pointer to one of these units.
  133.  
  134. io_Command: It is here you set the command flag which tells the
  135.             device what you actually want to do. There exist a
  136.             lot of different commands depending on which device
  137.             you are using.
  138.             
  139.             The commands can be divided into to groups. The
  140.             first group of commands is the standard device
  141.             commands like read and write. They are used by most
  142.             devices, and are defined in the same header file as
  143.             the request structure ("exec/io.h"). Se chapter 17
  144.             "Devices" for more information about these commands.
  145.  
  146.             (The printer device can only handle the commands
  147.             which are marked with a star "*".)
  148.  
  149.               CMD_RESET:  (*) Reset the device. Removes all
  150.                           queued commands and sets all fields
  151.                           to the default settings.
  152.  
  153.               CMD_READ:   Read (collect) data from the device.
  154.  
  155.               CMD_WRITE:  (*) Write (send) data to the device.
  156.  
  157.               CMD_UPDATE: Update the device.
  158.  
  159.               CMD_CLEAR:  Clears the device's own input buffer.
  160.  
  161.               CMD_STOP:   (*) Temporarily stops the device.
  162.  
  163.               CMD_START:  (*) Restarts the device after it has
  164.                           been stopped.
  165.  
  166.               CMD_FLUSH:  (*) Removes all queued commands.
  167.             
  168.             The second group contains all special device
  169.             commands. Each device chapter (18-29) contains a
  170.             complete list of each device's special commands,
  171.             together with full instructions on how to use them.
  172.             
  173.             The printer device uses four special commands, but
  174.             only two of these may be used by the standard
  175.             request block: (See the other structures for more
  176.             information about the two other commands.)
  177.  
  178.               PRD_RAWWRITE:   Sends raw (not translated)
  179.                               characters.
  180.  
  181.               PRD_QUERY:      Send this command if you want to
  182.                               receive some information about the
  183.                               printer device.
  184.  
  185. io_Flags:   This flag field is used by only some of the devices.
  186.  
  187. io_Error:   This field is set to 0 if the device managed to do
  188.             your request, else an error number is stored here.
  189.             Depending on which device you are using different
  190.             error messages are used. However, there exist four
  191.             standard error messages (defined in header file
  192.             "exec/errors.h"):
  193.             
  194.               IOERR_OPENFAIL:  Could not open the device.
  195.  
  196.               IOERR_ABORTED:   The request was aborted.
  197.  
  198.               IOERR_NOCMD:     A command that was not supported
  199.                                by the device was used.
  200.  
  201.               IOERR_BADLENGTH: Bad length of the command - data.
  202.  
  203.             If the printer device failed to do your request, one
  204.             of these error flags is returned:
  205.  
  206.               PDERR_CANCEL:         User cancelled the request.
  207.  
  208.               PDERR_NOTGRAPHICS:    The printer which the user
  209.                                     has can not handle
  210.                                     graphics.    
  211.  
  212.               PDERR_BADDIMENSION:   The printer dimension is
  213.                                     not valid.
  214.  
  215.               PDERR_INTERNALMEMORY: Not enough memory for the
  216.                                     printer device's internal
  217.                                     variables.
  218.  
  219.               PDERR_BUFFERMEMORY:   Not enough memory for the
  220.                                     print buffer.
  221.  
  222. io_Actual:  The number of bytes that was actually collected or
  223.             sent. If this number is not the same as the number
  224.             of bytes you wanted to collect/send, the
  225.             communication may have been interrupted.
  226.  
  227. io_Length:  The number of bytes you want to send or collect.
  228.  
  229. io_Data:    Pointer to where the data is which should be sent,
  230.             or pointer to where all data which is collected
  231.             should be stored.
  232.  
  233. io_Offset:  Offset value used by some devices.
  234.  
  235.  
  236.  
  237. 92.2.1.2  SPECIAL PRINTER COMMAND STRUCTURE
  238.  
  239. When you want to send special printer commands like "italics
  240. on", "boldface off", "subscript on" etc (a complete table of
  241. printer commands is listed below) you can do it in two ways:
  242.  
  243.   (A) You send the printer command's "Escape Sequence" in the
  244.       same way you send normal text. These escape sequences will
  245.       be translated by Preferences and then sent to the printer.
  246.      
  247.   (B) You send the printer command with help of a special
  248.       printer command request block (struct IOPrtCmdReq).
  249.  
  250. Both options will work equally well, but your code will look
  251. better if you use the special IOPrtCmdReq structure. (It is
  252. easier to understand what is happening, since escape sequences
  253. are usually not very informative and definitely not easy to
  254. remember.) All printer commands are also defined in the header
  255. file "devices/printer.h", and you are therefore recommended
  256. to use them instead of the escape sequences.
  257.  
  258. struct IOPrtCmdReq
  259. {
  260.   struct Message io_Message;
  261.   struct Device  *io_Device;
  262.   struct Unit    *io_Unit;
  263.   UWORD  io_Command;
  264.   UBYTE  io_Flags;
  265.   BYTE   io_Error;
  266.   UWORD  io_PrtCommand;
  267.   UBYTE  io_Parm0;
  268.   UBYTE  io_Parm1;
  269.   UBYTE  io_Parm2;
  270.   UBYTE  io_Parm3;
  271. };
  272.  
  273. io_Message:    This is the message that will be sent to your
  274.                reply port once the device has successfully or
  275.                not finished your request
  276.  
  277. io_Device:     Pointer to the printer device which is using
  278.                this request block.
  279.  
  280. io_Unit:       Not used by the printer device.
  281.  
  282. io_Command:    Set this field to PRD_PRTCOMMAND, and the device
  283.                will know that you want to send commands to the
  284.                printer. NOTE! The flag "PRD_PRTCOMMAND" should
  285.                only be used by IOPrtCmdReq structures!!!
  286.  
  287. io_Flags:      Not used.
  288.  
  289. io_Error:      This field is set to 0 if the printer device
  290.                managed to do your request, else an error number
  291.                is stored here:
  292.  
  293.                  PDERR_CANCEL:         User cancelled the
  294.                                        request.
  295.  
  296.                  PDERR_NOTGRAPHICS:    The printer which the
  297.                                        user has can not handle
  298.                                        graphics.    
  299.  
  300.                  PDERR_BADDIMENSION:   The printer dimension is
  301.                                        not valid.
  302.  
  303.                  PDERR_INTERNALMEMORY: Not enough memory for
  304.                                        the printer device's
  305.                                        internal variables.
  306.  
  307.                  PDERR_BUFFERMEMORY:   Not enough memory for
  308.                                        the print buffer.
  309.  
  310. io_PrtCommand: The command you want to send to the printer. See
  311.                below for a complete list of all printer
  312.                commands. Some of the commands require extra
  313.                parameters, and these parameters should be set
  314.                in the following four fields.
  315.  
  316. io_Parm0:      First parameter.
  317.  
  318. io_Parm1:      Second parameter.
  319.  
  320. io_Parm2:      Third parameter.
  321.  
  322. io_Parm3:      Fourth parameter.
  323.  
  324.  
  325.  
  326. 92.2.1.3  SPECIAL GRAPHIC STRUCTURE
  327.  
  328. When you want to print graphics you have to use the special
  329. IODRPReq structure. It will dump a specified rastport (see
  330. chapter 12 "Low Level Graphics" for more information about
  331. rastports) to the printer. Note that this request will only
  332. work if the user has a printer that supports graphics.
  333.  
  334. The IODRPReq structure look like this: (also defined in header
  335. file "devices/printer.h")
  336.  
  337. struct IODRPReq
  338. {
  339.   struct Message io_Message;
  340.   struct Device  *io_Device;
  341.   struct Unit    *io_Unit;
  342.   UWORD  io_Command;
  343.   UBYTE  io_Flags;
  344.   BYTE   io_Error;
  345.   struct RastPort *io_RastPort;
  346.   struct ColorMap *io_ColorMap;
  347.   ULONG  io_Modes;
  348.   UWORD  io_SrcX;
  349.   UWORD  io_SrcY;
  350.   UWORD  io_SrcWidth;
  351.   UWORD  io_SrcHeight;
  352.   LONG   io_DestCols;
  353.   LONG   io_DestRows;
  354.   UWORD  io_Special;
  355. };
  356.  
  357.  
  358. io_Message:    This is the message that will be sent to your
  359.                reply port once the device has successfully or
  360.                not finished your request
  361.  
  362. io_Device:     Pointer to the printer device which is using
  363.                this request block.
  364.  
  365. io_Unit:       Not used by the printer device.
  366.  
  367. io_Command:    Set this field to PRD_PRTCOMMAND, and the device
  368.                will know that you want to send commands to the
  369.                printer. NOTE! The flag "PRD_PRTCOMMAND" should
  370.                only be used by IOPrtCmdReq structures!!!
  371.  
  372. io_Flags:      Not used.
  373.  
  374. io_Error:      This field is set to 0 if the printer device
  375.                managed to do your request, else an error number
  376.                is stored here:
  377.  
  378.                  PDERR_CANCEL:         User cancelled the
  379.                                        request.
  380.  
  381.                  PDERR_NOTGRAPHICS:    The printer which the
  382.                                        user has can not handle
  383.                                        graphics.    
  384.  
  385.                  PDERR_BADDIMENSION:   The printer dimension is
  386.                                        not valid.
  387.  
  388.                  PDERR_INTERNALMEMORY: Not enough memory for
  389.                                        the printer device's
  390.                                        internal variables.
  391.  
  392.                  PDERR_BUFFERMEMORY:   Not enough memory for
  393.                                        the print buffer.
  394.  
  395. io_RastPort:   Pointer to the RastPort that should be printed.
  396.  
  397. io_ColorMap:   Pointer to the ColorMap structure which contains
  398.                all information about the RastPort's colours. 
  399.  
  400. io_Modes:      The ViewPort's display modes. The information
  401.                is used to convert the picture which will be
  402.                printed to the correct aspects. (On a low
  403.                resolution screen each pixels is equally wide as
  404.                tall. However, on a high resolution screen, each
  405.                pixel is only half as wide as it is tall. The
  406.                same applies for interlaced and non interlaced
  407.                screens.) The printer device must also know if
  408.                you want to print a "normal" picture, or a
  409.                picture with one of the special display modes
  410.                like "HAM" or "Extrahalf Brite". The following
  411.                flags may be used:
  412.  
  413.                HIRES:  Set this flag if you want to print a high
  414.                        resolution screen. If this flag is not
  415.                        set, the printer device assumes that you
  416.                        are using a low resolution screen.
  417.  
  418.                LACE:   Set this flag if you want to print an
  419.                        interlaced picture. If this flag is not
  420.                        set, the printer device assumes that you
  421.                        are using a non-interlaced picture.
  422.  
  423.                HAM:    Set this flag if you want to print a
  424.                        "HAM" picture.
  425.  
  426.                EXTRA_HALFBRITE: Set this flag if you want to
  427.                        print an "extra halfbrite" picture.
  428.  
  429.                PUALPF: Set this flag if you want to print a dual
  430.                        playfields screen.
  431.  
  432.                Note that the simplest way is to copy the
  433.                Viewport structure's "modes" field. You will then
  434.                not risk to forget one or more display flags.
  435.  
  436. io_SrcX:       X offset of the source picture.
  437.  
  438. io_SrcY:       Y offset of the source picture.
  439.  
  440. io_SrcWidth:   Width of the source picture.
  441.  
  442. io_SrcHeight:  Height of the source picture.
  443.  
  444. io_DestCols:   Width of the printed picture. If the special
  445.                flag "SPECIAL_MILCOLS" is set, the width is in
  446.                1/1000". If the special flag "SPECIAL_FULLCOLS"
  447.                is set, this field is ignored by the printer
  448.                device. (The picture will be as wide as
  449.                possible.) Finally, if the special flag
  450.                "SPECIAL_FRACCOLS" is set this field specifies
  451.                the size as a fraction of the maximum width.
  452.                
  453. io_DestRows:   Height of the printed picture. If the special
  454.                flag "SPECIAL_MILROWS" is set, the height is in
  455.                1/1000". If the special flag "SPECIAL_FULLROWS"
  456.                is set, this field is ignored by the printer
  457.                device. (The picture will be as tall as
  458.                possible.) Finally, if the special flag
  459.                "SPECIAL_FRACROWS" is set this field specifies
  460.                the size as a fraction of the maximum height.
  461.  
  462. io_Special:    There exist several special graphical printing
  463.                modes. Here is a complete list of flags that may
  464.                be used:
  465.  
  466.                SPECIAL_MILCOLS:    If this flag is set the
  467.                                    "io_DestCols" field specifies
  468.                                    the width in 1/1000".
  469.  
  470.                SPECIAL_MILROWS:    If this flag is set the
  471.                                    "io_DestRows" field specifies
  472.                                    the height in 1/1000".
  473.    
  474.                SPECIAL_FULLCOLS:   Set this flag if you want the
  475.                                    width of the printed picture
  476.                                    to be as wide as possible.
  477.    
  478.                SPECIAL_FULLROWS:   Set this flag if you want the
  479.                                    height of the printed picture
  480.                                    to be as tall as possible.
  481.    
  482.                SPECIAL_FRACCOLS:   If this flag is set the
  483.                                    "io_DestCols" field specifies
  484.                                    the width as a fraction of
  485.                                    the maximum width.
  486.    
  487.                SPECIAL_FRACROWS:   If this flag is set the
  488.                                    "io_DestRows" field specifies
  489.                                    the height as a fraction of
  490.                                    the maximum height.
  491.  
  492.                SPECIAL_CENTER:     Set this flag if you want the
  493.                                    picture to be centered on the
  494.                                    paper.
  495.    
  496.                SPECIAL_ASPECT:     Set this flag if you want to
  497.                                    use the correct aspect ratio
  498.                                    of the picture. If you set
  499.                                    the flag "SPECIAL_FULLCOLS"
  500.                                    and this "SPECIAL_ASPECT"
  501.                                    flag the printed picture will
  502.                                    be as large as possible, but
  503.                                    still with the right aspects. 
  504.    
  505.                SPECIAL_DENSITY1:   Set this flag if you want the
  506.                                    picture to be printed with
  507.                                    the printer's lowest
  508.                                    resolution.
  509.    
  510.                SPECIAL_DENSITY2:   Next resolution.
  511.    
  512.                SPECIAL_DENSITY3:   Next resolution.
  513.    
  514.                SPECIAL_DENSITY4:   Next resolution.
  515.    
  516.                SPECIAL_DENSITY5:   Next resolution.
  517.    
  518.                SPECIAL_DENSITY6:   Next resolution.
  519.    
  520.                SPECIAL_DENSITY7:   Use the printer's highest
  521.                                    (finest) resolution.
  522.    
  523.                SPECIAL_NOFORMFEED: Set this flag if you do not
  524.                                    want that the paper is
  525.                                    ejected after each time you
  526.                                    have printed graphics.
  527.    
  528.                SPECIAL_TRUSTME:    Set this flag if you do not
  529.                                    want the printer to reset
  530.                                    any parameters while
  531.                                    printing.
  532.  
  533.  
  534.  
  535. 92.2.1.4  HOW TO CREATE THE PRINTER REQUEST BLOCK
  536.  
  537. To create a printer request block, use the CreateExtIO()
  538. function. Since there exist three different types of structures
  539. that are needed, the printer device assumes that you are using
  540. a union of these three structures. The union is sadly not
  541. declared in any header file, so you have to declare it
  542. yourself. It should look like this:
  543.  
  544. union printerIO
  545. {
  546.   struct IOStdReq ios;
  547.   struct IODRPReq iodrp;
  548.   struct IOPrtCmdReq iopc;
  549. };
  550.  
  551.  
  552. The CreateExtIO function should always be used when you want to
  553. create a request block which is not of the normal size
  554. (struct IOStdReq).
  555.  
  556. Synopsis: prt_req = CreateExtIO( msg_port, size );
  557.  
  558. prt_req:  (struct IORequest *) If CreateExtIO() managed to
  559.           allocate and initialize the request block it returns
  560.           a pointer to it, else the function will return NULL.
  561.           (Note that you have to do some "casting" here, since
  562.           the compiler expects that the function returns a
  563.           pointer to a normal IORequest structure, but this
  564.           function is used when you create other (larger) types
  565.           of request block. Se example for more information.)
  566.  
  567. msg_port: (struct MsgPort *) Pointer to a message port to which
  568.           the device will send a message to each time it has
  569.           completed your request. 
  570.  
  571. size:     The size (in bytes) of the request block. Use the
  572.           function sizeof() to find out how big the special 
  573.           request block is. Example: sizeof( union printerIO );
  574.  
  575.  
  576.  
  577. 92.2.2  OPEN THE PRINTER DEVICE
  578.  
  579. As with all devices you have to open a message port through
  580. which the printer device can communicate with you, and allocate
  581. a request block (a printerIO union), before you may open the
  582. device itself.
  583.  
  584.   1. Open a message port: (Since it is only our task and the
  585.      device that will use the message port, we do not need
  586.      to make it "public", hence no name. Priority should as
  587.      usual be set to 0, normal priority.)
  588.  
  589.      struct MsgPort *replymp;
  590.  
  591.      replymp = (struct MsgPort *)
  592.        CreatePort( NULL, 0 );
  593.  
  594.      if( !replymp )
  595.        clean_up( "Could not create the reply port!" );
  596.  
  597.  
  598.   2. Allocate a request block of type printerIO union. Since
  599.      the printer request block is larger than normal request
  600.      blocks (IOStdReq structure) it must be created with
  601.      the CreateExtIO() function.
  602.  
  603.      union printerIO printer_req;
  604.  
  605.      printer_req = (union printerIO *)
  606.        CreateExtIO( replymp, sizeof( union printerIO ) );
  607.  
  608.      if( !printer_req )
  609.        clean_up( "Not enough memory!" );
  610.  
  611.  
  612.   3. Once the message port and the request block have
  613.      successfully been created you may open the printer device.
  614.  
  615.      UBYTE error;
  616.  
  617.      /* Open the printer device: */
  618.      error = OpenDevice( "printer.device", 0, printer_req, 0 );
  619.  
  620.      if( error )
  621.        clean_up( "Could not open the Printer Device!" );
  622.  
  623.  
  624.  
  625. 9.2.3  PRINT TEXT
  626.  
  627. When the printer device has been opened you may start to send
  628. text to the printer. When printing normal text you should use
  629. the "IOStdReq" structure of the printerIO union. You can either
  630. send text which will not be translated (raw text) to the
  631. printer, or you can send text that will be translated.
  632.  
  633. The advantage of sending text that is translated by Preferences
  634. is that the characters you send will also be the same when
  635. printed. (Many printers have their own list of foreign
  636. characters. And if the characters are not translated, you
  637. never know what will be printed.)
  638.  
  639. The second reason for translating text is that "escape
  640. sequences" (like "underline on", "boldface off", "NLQ" etc...)
  641. will be translated into the printer's own printer commands.
  642. If you write a program that uses "escape sequences" you know
  643. that it will work on all printers (as long as they support
  644. your commands). If you on the other hand send special
  645. untranslated printer commands that are unlike for some type
  646. of printer models, your program will not work with other
  647. types of printers. 
  648.  
  649. Raw (untranslated) text should only be used when it is really
  650. needed (which is not very often). If you want to dump the
  651. printers own ASCII codes it can be useful to send untranslated
  652. characters, but otherwise I recommend you to only send
  653. translated text.
  654.   
  655. To print text simply do like this:
  656.  
  657.   1. Set the "io_Command" field to CMD_WRITE if you want the
  658.      text to be translated by Preferences. On the other hand,
  659.      if you want to send raw (untranslated) text use the
  660.      "PRD_RAWWRITE" command.
  661.  
  662.   2. Set the "io_Length" field to the number of characters
  663.      (bytes) you want to send.
  664.  
  665.   3. Give the "io_Data" pointer the address of your data buffer
  666.      which contains the text you want to print. 
  667.  
  668.   4. Now send the request to the printer device, by either a
  669.      DoIO() or SendIO() function call.
  670.      
  671.      If you want to wait for the device to finish your request
  672.      before your program continues you should use the
  673.      "synchronous" command DoIO(). If you instead want to
  674.      continue to do something while the printer is working,
  675.      you should use the "asynchronous" command SendIO().
  676.  
  677.  
  678. Here is an example on how to send text to the printer. This is
  679. a synchronous request, which means the program is halted while
  680. the printer is working.
  681.  
  682.   /* Pointer to an already initialized printer request block: */
  683.   union printerIO *printer_req
  684.  
  685.   /* The text we want to print: (Oh no, not that text again!) */
  686.   BYTE data[13] = "Hello world!"
  687.  
  688.   /* Store any error values here: */
  689.   BYTE error;
  690.  
  691.  
  692.   /* We want to print some translated text: (If we want */
  693.   /* to send raw, untranslated, text we should use the  */
  694.   /* "PRD_RAWWRITE" command instead of "CMD_WRITE".)    */
  695.   printer_req->ios.io_Command = CMD_WRITE;
  696.  
  697.   /* Give the start address of our data: */
  698.   printer_req->ios.io_Data = (APTR) data;
  699.  
  700.   /* Set number of chracters that should be printed: */
  701.   /* (12 characters - bytes)                         */
  702.   printer_req->ios.io_Length = 12;
  703.  
  704.   /* Do our request: (This is a task sleep) */
  705.   error = DoIO( printer_req );
  706.  
  707.   /* Check if the request was successfully executed: */
  708.   if( error )
  709.     printf( "Problems! Error code: %d\n", error );
  710.  
  711.  
  712.  
  713. Here is another example, but this time we use an asynchronous
  714. request, which means the program continues to run while the
  715. printer is working.
  716.  
  717.   /* Pointer to an already initialized printer request block: */
  718.   union printerIO *printer_req
  719.  
  720.   /* The text we want to print: */
  721.   BYTE data[13] = "Hello again!"
  722.  
  723.   /* Store any error values here: */
  724.   BYTE error;
  725.  
  726.   /* Temporary pointer: */
  727.   union printerIO *ptr;
  728.  
  729.  
  730.   /* We want to print some translated text: (If we want */
  731.   /* to send raw, untranslated, text we should use the  */
  732.   /* "PRD_RAWWRITE" command instead of "CMD_WRITE".)    */
  733.   printer_req->ios.io_Command = CMD_WRITE;
  734.  
  735.   /* Give the start address of our data: */
  736.   printer_req->ios.io_Data = (APTR) data;
  737.  
  738.   /* Set number of chracters that should be printed: */
  739.   /* (12 characters - bytes)                         */
  740.   printer_req->ios.io_Length = 12;
  741.  
  742.   /* Do our request and return immediately: */
  743.   SendIO( printer_req );
  744.  
  745.  
  746.   /* As long as the pointer is not pointing to */
  747.   /* the request we should stay in the loop:   */
  748.   ptr = NULL;
  749.   while( ptr == NULL )
  750.   {
  751.     /*   ... do something ...    */
  752.     /* Well, I do not know what. */
  753.   
  754.     /* Check if the request has been completed: (If the  */
  755.     /* request has been completed CheckIO() will return  */
  756.     /* a pointer to the request, else NULL is returned.) */
  757.     ptr = (union printerIO *) CheckIO( printer_req );
  758.   }
  759.  
  760.   /* At last the request was completed! */
  761.  
  762.  
  763.   /* Remove the request block's message. (The ptr and   */
  764.   /* printer_req are in this example identical, so it   */
  765.   /* does not matter whichever you use. The parenthesis */
  766.   /* around the expression is actually unnecessary, but */
  767.   /* this looks better.)                                */
  768.   Remove( &(ptr->ios.io_Message.mn_Node) );
  769.  
  770.  
  771.   /* Check if everything is OK? */
  772.   if( ptr->ios.io_Error )
  773.     printf( "Problems while printing!\n" );
  774.  
  775.  
  776.  
  777. 9.2.4  SEND SPECIAL COMMANDS TO THE PRINTER
  778.  
  779. Most printers can use different printing styles like underlined,
  780. italics and boldface just to mention a few. Usually you can
  781. use several different fonts and expand and compress the
  782. characters, as well as setting margins, use proportional styles,
  783. handle foreign character sets etc...
  784.  
  785. All these features are controlled by special printer commands.
  786. Most printers have their own set of unique commands. Luckily
  787. we do not need to know about them. We simply use a set of
  788. universal printer commands listed below, and Preferences will
  789. automatically translate these into the specified printer's
  790. own commands.
  791.  
  792. There exist two ways to send the printer commands to the
  793. printer. Either you send the "escape sequences" together with
  794. the rest of the text, or you can send the commands with a
  795. separate request block (struct IOPrtCmdReq). Since escape
  796. sequences are rather difficult to remember it usually looks
  797. better if you use the separate request block technique.
  798.  
  799. When you send a printer command with help of the request block
  800. you should use the IOPrtCmdReq structure. You set the
  801. io_Command field to "PRD_PRTCOMMAND", the "io_PrtCommand"
  802. field to the command you want to send, and up to four
  803. parameters may also be sent if needed by initializing the
  804. "io_Parm0" to "io_Parm3" fields. Here is an example:
  805.  
  806.  
  807.   /* We want to send a printer command to the printer: */
  808.   printer_req->iopc.io_Command = PRD_PRTCOMMAND;
  809.  
  810.   /* Set the printer command: [Underline On] */
  811.   printer_req->iopc.io_PrtCommand = aSGR4;
  812.  
  813.   /* Set the parameters: */
  814.   printer_req->iopc.io_Parm0 = 0; /* Nothing */
  815.   printer_req->iopc.io_Parm1 = 0; /* Nothing */
  816.   printer_req->iopc.io_Parm2 = 0; /* Nothing */
  817.   printer_req->iopc.io_Parm3 = 0; /* Nothing */
  818.  
  819.   /* Do the request: */
  820.   DoIO( printer_req );
  821.  
  822.  
  823. Here is the complete list of printer commands and escape
  824. sequences. The names are defined in header file "devices/
  825. printer.h".
  826.  
  827. If you use the escape sequences you should send the commands
  828. exactly as written below with one difference - you should
  829. replace the character "n" with a (ASCII) value. To set the top
  830. and bottom margins to 2 and 4, send the escape sequence:
  831. "ESC[2;4r" (without quotations).
  832.  
  833.   Name   Command Esc Seq   Function                Defined by
  834.   --------------------------------------------------------------
  835.   aRIS       0   ESCc      reset                   ISO 
  836.   aRIN       1   ESC#1     initialize              Amiga
  837.   aIND       2   ESCD      lf                      ISO
  838.   aNEL       3   ESCE      return,lf               ISO
  839.   aRI        4   ESCM      reverse lf              ISO
  840.  
  841.   aSGR0      5   ESC[0m    normal char set         ISO
  842.   aSGR3      6   ESC[3m    italics on              ISO
  843.   aSGR23     7   ESC[23m   italics off             ISO 
  844.   aSGR4      8   ESC[4m    underline on            ISO 
  845.   aSGR24     9   ESC[24m   underline off           ISO 
  846.   aSGR1     10   ESC[1m    boldface on             ISO 
  847.   aSGR22    11   ESC[22m   boldface off            ISO 
  848.   aSFC      12   ESC[3nm   set foreground color    ISO 
  849.   aSBC      13   ESC[4nm   set background color    ISO 
  850.  
  851.   aSHORP0   14   ESC[0w    normal pitch            DEC 
  852.   aSHORP2   15   ESC[2w    elite on                DEC 
  853.   aSHORP1   16   ESC[1w    elite off               DEC 
  854.   aSHORP4   17   ESC[4w    condensed fine on       DEC 
  855.   aSHORP3   18   ESC[3w    condensed off           DEC 
  856.   aSHORP6   19   ESC[6w    enlarged on             DEC 
  857.   aSHORP5   20   ESC[5w    enlarged off            DEC 
  858.  
  859.   aDEN6     21   ESC[6"z   shadow print on         DEC (sort of) 
  860.   aDEN5     22   ESC[5"z   shadow print off        DEC 
  861.   aDEN4     23   ESC[4"z   doublestrike on         DEC 
  862.   aDEN3     24   ESC[3"z   doublestrike off        DEC 
  863.   aDEN2     25   ESC[2"z   NLQ on                  DEC 
  864.   aDEN1     26   ESC[1"z   NLQ off                 DEC 
  865.  
  866.   aSUS2     27   ESC[2v    superscript on          Amiga 
  867.   aSUS1     28   ESC[1v    superscript off         Amiga 
  868.   aSUS4     29   ESC[4v    subscript on            Amiga 
  869.   aSUS3     30   ESC[3v    subscript off           Amiga 
  870.   aSUS0     31   ESC[0v    normalize the line      Amiga 
  871.   aPLU      32   ESCL      partial line up         ISO 
  872.   aPLD      33   ESCK      partial line down       ISO 
  873.   
  874.                            Char set: or Typface:
  875.   aFNT0     34   ESC(B       US            0       DEC
  876.   aFNT1     35   ESC(R       French        1       DEC
  877.   aFNT2     36   ESC(K       German        2       DEC
  878.   aFNT3     37   ESC(A       UK            3       DEC
  879.   aFNT4     38   ESC(E       Danish        4       DEC
  880.   aFNT5     39   ESC(H       Sweden        5       DEC
  881.   aFNT6     40   ESC(Y       Italian       6       DEC
  882.   aFNT7     41   ESC(Z       Spanish       7       DEC
  883.   aFNT8     42   ESC(J       Japanese      8       Amiga
  884.   aFNT9     43   ESC(6       Norweign      9       DEC
  885.   aFNT10    44   ESC(C       Danish II    10       Amiga
  886.  
  887.   aPROP2    45   ESC[2p    proportional on         Amiga 
  888.   aPROP1    46   ESC[1p    proportional off        Amiga 
  889.   aPROP0    47   ESC[0p    proportional clear      Amiga 
  890.  
  891.   aTSS      48   ESC[n E   set proportional offset ISO 
  892.   aJFY5     49   ESC[5 F   auto left justify       ISO 
  893.   aJFY7     50   ESC[7 F   auto right justify      ISO 
  894.   aJFY6     51   ESC[6 F   auto full justify       ISO 
  895.   aJFY0     52   ESC[0 F   auto justify off        ISO 
  896.   aJFY3     53   ESC[3 F   letter space (justify)  ISO (special) 
  897.   aJFY1     54   ESC[1 F   word fill(auto center)  ISO (special) 
  898.  
  899.   aVERP0    55   ESC[0z    1/8" line spacing       Amiga 
  900.   aVERP1    56   ESC[1z    1/6" line spacing       Amiga 
  901.   aSLPP     57   ESC[nt    set form length n       DEC 
  902.   aPERF     58   ESC[nq    perf skip n (n>0)       Amiga 
  903.   aPERF0    59   ESC[0q    perf skip off           Amiga 
  904.  
  905.   aLMS      60   ESC#9     Left margin set         Amiga 
  906.   aRMS      61   ESC#0     Right margin set        Amiga 
  907.   aTMS      62   ESC#8     Top margin set          Amiga 
  908.   aBMS      63   ESC#2     Bottom marg set         Amiga 
  909.  
  910.   aSTBM     64   ESC[n;nr  T&B margins             DEC 
  911.   aSLRM     65   ESC[n;ns  L&R margin              DEC 
  912.   aCAM      66   ESC#3     Clear margins           Amiga 
  913.   aHTS      67   ESCH      Set horiz tab           ISO 
  914.   aVTS      68   ESCJ      Set vertical tabs       ISO 
  915.  
  916.   aTBC0     69   ESC[0g    Clr horiz tab           ISO 
  917.   aTBC3     70   ESC[3g    Clear all h tab         ISO 
  918.   aTBC1     71   ESC[1g    Clr vertical tabs       ISO 
  919.   aTBC4     72   ESC[4g    Clr all v tabs          ISO 
  920.   aTBCAL    L73  ESC#4     Clr all h & v tabs      Amiga 
  921.   aTBSAL    L74  ESC#5     Set default tabs        Amiga 
  922.   aEXTEN    D75  ESC[n"x   extended commands       Amiga 
  923.   aRAW      76   ESC[n"r   Next 'Pn' chars are raw Amiga 
  924.   
  925.   
  926.   Suggested typefaces are:
  927.   ---------------------------
  928.  
  929.    0 - default typeface.
  930.    1 - Line Printer or equiv.
  931.    2 - Pica or equiv.
  932.    3 - Elite or equiv.
  933.    4 - Helvetica or equiv.
  934.    5 - Times Roman or equiv.
  935.    6 - Gothic or equiv.
  936.    7 - Script or equiv.
  937.    8 - Prestige or equiv.
  938.    9 - Caslon or equiv.
  939.   10 - Orator or equiv.
  940.  
  941.  
  942.   Amiga: Unique command for the Amiga.
  943.   ISO:   Defined by the International Standards Organization.
  944.   DEC:   Defined by Digital Equipment Corporation.
  945.   
  946.  
  947.  
  948. 9.2.5  PRINT GRAPHICS
  949.  
  950. The printer device does not only handle text, it can also be
  951. used to print graphics. To do this we have to use the IODRPReq
  952. structure of the request block. We give it a pointer to a
  953. RastPort which should be printed and sets some special values
  954. like size, resolution etc. The rest is then automatically done.
  955.  
  956. Note that some printers does not support graphics, and thus
  957. your request will be returned immediately with an error value
  958. "PDERR_NOTGRAPHICS".
  959.  
  960. Here is what we have to do:
  961.  
  962.   1. Set the command "PRD_DUMPRPORT".
  963.  
  964.   2. Give the request block a pointer to the RastPort we want
  965.      to print.
  966.  
  967.   3. We must also give the request block a pointer to a ColorMap
  968.      structure which contains the picture's colour values.
  969.  
  970.   4. Tell the request block what screen "mode" the RastPort is
  971.      made for. The information is used to convert the picture
  972.      which will be printed to the correct aspects.
  973.      
  974.      On a low resolution screen each pixels is equally wide as
  975.      tall. However, on a high resolution screen, each pixel is
  976.      only half as wide as it is tall. The same applies for
  977.      interlaced and non interlaced screens.
  978.      
  979.      The printer device must also know if you want to print a
  980.      "normal" picture, or a picture with one of the Amiga's
  981.      special display modes like "HAM" or "Extrahalf Brite".
  982.      
  983.      If you print a RastPort that is connected to a ViewPort,
  984.      you can simply copy the Viewport structure's "Modes"
  985.      field. If you have defined a RastPort that is not used
  986.      to be displayed just to be printed, set the field to 0.
  987.  
  988.   5. Tell the device if the whole RastPort should be printed,
  989.      or just a part of it. 
  990.  
  991.   6. You must also specify how large the printed picture should
  992.      be. Note that most printers have a much higher resolution
  993.      than normal screens. You can therefore usually print a
  994.      picture that is much smaller than the screen, and still
  995.      have all details as the original.
  996.  
  997.   7. Finally you can set some special graphical flags as
  998.      described above.
  999.  
  1000.  
  1001. Here is an example:
  1002.  
  1003.   /* Store possible error numbers here: */
  1004.   BYTE error;
  1005.  
  1006.   /* An already initialized printer request block: */
  1007.   union printerIO *printer_req,
  1008.  
  1009.   /* Pointer to a RastPort: */
  1010.   struct RastPort *rp,
  1011.  
  1012.   /* Pointer to a ColourMap: */
  1013.   struct ColorMap *cm,
  1014.  
  1015.  
  1016.   /* We want to dump a RastPort to the printer: */
  1017.   printer_req->iodrp.io_Command = PRD_DUMPRPORT;
  1018.  
  1019.   /* Set a pointer to the RastPort structure: */
  1020.   printer_req->iodrp.io_RastPort = rp;
  1021.  
  1022.   /* Set a pointer to the ColorMap structure: */
  1023.   printer_req->iodrp.io_ColorMap = cm;
  1024.  
  1025.   /* Set the "display" modes:         */
  1026.   /* (0 = aspect 1:1, normal screen.) */
  1027.   printer_req->iodrp.io_Modes = 0;
  1028.  
  1029.   /* X position of the source: (10 pixels out) */
  1030.   printer_req->iodrp.io_SrcX = 10;
  1031.  
  1032.   /* Y position of the source: (10 pixels down) */
  1033.   printer_req->iodrp.io_SrcY = 10;
  1034.  
  1035.   /* Width of the source: (100 pixels wide) */
  1036.   printer_req->iodrp.io_SrcWidth = 100;
  1037.  
  1038.   /* Height of the source: (50 pixels high) */
  1039.   printer_req->iodrp.io_SrcHeight = 50;
  1040.  
  1041.   /* The width of the printed picture: (This field is in     */
  1042.   /* this example ignored by the printer device since the    */
  1043.   /* special flag "SPECIAL_FULLCOLS" is set. Maximum width.) */ 
  1044.   printer_req->iodrp.io_DestCols = 0;
  1045.  
  1046.   /* The height of the printed picture: (This field is in  */
  1047.   /* this example also ignored by the printer device since */
  1048.   /* the special flag "SPECIAL_ASPECT" is set. The height  */
  1049.   /* will therefore be automatically calculated.)          */ 
  1050.   printer_req->iodrp.io_DestRows = 0;
  1051.  
  1052.   /* Set the special printing commands: (Full width and     */
  1053.   /* the height is automatically set so the printed picture */
  1054.   /* will have the right aspects.)                          */
  1055.   printer_req->iodrp.io_Special =
  1056.     SPECIAL_FULLCOLS | SPECIAL_ASPECT;
  1057.  
  1058.  
  1059.   /* Do our request: */
  1060.   error = DoIO( printer_req );
  1061.  
  1062.   /* Check if the request was successfully executed: */
  1063.   if( error )
  1064.     printf( "Problems while printing!\n" );
  1065.  
  1066.  
  1067.  
  1068. 9.2.6  ERRORS
  1069.  
  1070. When you are using the printer device it sometimes happens
  1071. that your request was not successfully executed, and you have
  1072. encounter an error message. Usually it is easy to guess what
  1073. went wrong, but it is always good to check what really happened.
  1074.  
  1075. You will either receive the error message from the function you
  1076. just called (for example, DoIO() returns 0 or an error number),
  1077. or you can check the request block to see if there were any
  1078. problems. (The io_Error filed of the request block either
  1079. contains 0, which means everything is OK, or an error number.)
  1080.  
  1081. Here is a complete list of the printer device error messages:
  1082.  
  1083.   PDERR_CANCEL:         The user cancelled the request. If you
  1084.                         receive this error you should not
  1085.                         start new printer requests until the
  1086.                         user says he/she wants to print again.
  1087.                         It is very annoying if you have 
  1088.                         cancelled a printout but the program 
  1089.                         continues to write new data to the
  1090.                         printer. If you have issued several
  1091.                         asynchronous requests after each other
  1092.                         and you receive this message, it is
  1093.                         usually best to try to remove the
  1094.                         queued requests.
  1095.  
  1096.   PDERR_NOTGRAPHICS:    The printer which the user has can not
  1097.                         handle graphics.    
  1098.  
  1099.   PDERR_BADDIMENSION:   The dimension of the printout is not
  1100.                         valid.
  1101.  
  1102.   PDERR_INTERNALMEMORY: Not enough memory for the printer
  1103.                         device's internal variables.
  1104.  
  1105.   PDERR_BUFFERMEMORY:   Not enough memory for the print buffer.
  1106.  
  1107.  
  1108. While you are using the printer device it may happen that you
  1109. also receive error messages from Exec. (Exec is handling all
  1110. stuff like messages, requests, tasks and so on.) Here is
  1111. a complete list of exec error messages: (defined in the header
  1112. file "exec/errors.h")
  1113.  
  1114.   IOERR_OPENFAIL  The device (unit) could not be opened.
  1115.   
  1116.   IOERR_ABORTED   When you abort a previously started request
  1117.                   by calling the AbortIO() function, the
  1118.                   "io_Error" filed of that request is set to
  1119.                   "IOERR_ABORTED". If you find a request
  1120.                   block with this flag set, you know that
  1121.                   it has been aborted.
  1122.   
  1123.   IOERR_NOCMD     You tried to use a command that is not
  1124.                   supported by the printer device.
  1125.   
  1126.   IOERR_BADLENGTH The length of the request was not valid.
  1127.  
  1128.  
  1129.  
  1130. 9.2.7  CLEAN UP
  1131.  
  1132. As usual on the Amiga you must remember to close and return
  1133. everything you have opened or allocated. If you do not close
  1134. the printer device after you a lot of memory is wasted.
  1135. The routine is very similar to how you close the parallel
  1136. device which was described in the previous chapter.
  1137.  
  1138. Here is a list of what you have to do:
  1139.  
  1140.   1. All requests you have started with SendIO() or BeginIO()
  1141.      (asynchronous commands) must either have been completed
  1142.      or aborted before you may close the device. It is a very
  1143.      common error to forget this, and it can be hard to find
  1144.      this bug. Usually the program will work fine (the command
  1145.      was completed in time), but now and then your program will
  1146.      crash (the command was completed after the device have
  1147.      been closed).
  1148.  
  1149.      A simple way is to abort all commands that have not
  1150.      reported that they have been completed, but this is not
  1151.      always good way to do it. (The last commands may be
  1152.      important and should therefore not be aborted.)
  1153.      
  1154.      If you do not want to abort the command, you should
  1155.      instead wait for it to be completed. The WaitIO()
  1156.      function is simple to use, and will put your program
  1157.      to sleep while waiting, so no computer time is wasted.
  1158.      If the request has already been completed, the function
  1159.      will return immediately. WaitIO() will also remove the
  1160.      message from the reply port. It is a very useful and
  1161.      simple function to use, but do NOT try to wait for
  1162.      a request that has not been started!
  1163.  
  1164.      Here is an example on how to wait for a request to be
  1165.      completed: (If the request already has been completed
  1166.      it does not matter, WaitIO() will then simply return
  1167.      immediately. Note that we do not have to remove any
  1168.      messages from the reply port if we use WaitIO().)
  1169.  
  1170.        /* Store possible error numbers here: */
  1171.        UBYTE error;
  1172.      
  1173.        /* ... */
  1174.      
  1175.        /* Wait for the request to be completed: */
  1176.        error = WaitIO( printer_req );
  1177.      
  1178.        /* Everything OK? */
  1179.        if( error )
  1180.          printf( "Something went wrong!" );
  1181.  
  1182.        /* Well, successful or not, we may now */
  1183.        /* close the device!                   */
  1184.  
  1185.  
  1186.      To abort a request, simply use the AbortIO() function:
  1187.  
  1188.        /* Try to abort a previously started request:  */
  1189.        /* (Do not try to abort a request that has not */
  1190.        /* been started!)                              */
  1191.        AbortIO( printer_req );
  1192.  
  1193.  
  1194.   2. When all requests have been completed or aborted you may
  1195.      close the printer device. (Requests that have been started
  1196.      by calling the DoIO() function have already been completed
  1197.      before your program wakes up, and thus you do not need to
  1198.      wait for these.)
  1199.      
  1200.      The printer device is closed as all other devices, by
  1201.      calling the CloseDevice() function. Here is an example:
  1202.  
  1203.        /* Close the Printer Device: */ 
  1204.        CloseDevice( printer_req );
  1205.  
  1206.  
  1207.   3. You should now return all request blocks you have
  1208.      allocated. The printer request block (union printerIO)
  1209.      is an extended request block, and should be deleted by
  1210.      the DeleteExtIO() function.
  1211.  
  1212.      /* Deallocate the printer request block: */
  1213.      DeleteExtIO( printer_req, sizeof(union printerIO) );
  1214.      
  1215.      Note that ALL request blocks that have been allocated,
  1216.      must be removed!
  1217.  
  1218.  
  1219.   4. Finally you should close all message ports you have
  1220.      previously opened. Simply use the DeletePort() function
  1221.      as this example demonstrates:
  1222.  
  1223.        /* Remove the replyport: */
  1224.        DeletePort( replymp);
  1225.  
  1226.  
  1227. Please be careful with how your program terminates! Your
  1228. program should not only run fine, but it should also allow
  1229. other programs to run after and simultaneously. Remember that
  1230. your program must also be able to quit nice and neatly even if
  1231. it had to terminate too early because of some fatal error. The
  1232. cleaning up should only be done where it is needed, and if you
  1233. have not allocated the memory or opened the device before your
  1234. program quits, you should of course NOT try to free these
  1235. resources! If you do the Amiga will most certainly crash! Too
  1236. many programs contain this very annoying error. Make sure yours
  1237. will not be one of those.
  1238.  
  1239.  
  1240.  
  1241. 9.3  A COMPLETE EXAMPLE
  1242.  
  1243. Here is a simple but complete example on how to print some
  1244. text. For more information see the Examples which are stored
  1245. together with this document.
  1246.  
  1247.  
  1248. #include <exec/types.h>       /* Data types.             */
  1249. #include <exec/errors.h>      /* Exec error messages.    */
  1250. #include <devices/printer.h>  /* Printer Device.         */
  1251. #include <exec/io.h>          /* Standard request block. */
  1252.  
  1253.  
  1254. /* Declare how the printer request block look like: */
  1255. union printerIO
  1256. {
  1257.   struct IOStdReq ios;
  1258.   struct IODRPReq iodrp;
  1259.   struct IOPrtCmdReq iopc;
  1260. };
  1261.  
  1262.  
  1263. /* Declare a pointer to our reply port: */
  1264. struct MsgPort *replymp = NULL;
  1265.  
  1266. /* Declare a pointer our printer request block: */
  1267. union printerIO *printer_req = NULL;
  1268.  
  1269. /* Store the printer device error here: */
  1270. UWORD printer_dever = TRUE;
  1271.  
  1272. /* Declare our data buffer: (25 characters) */
  1273. BYTE buffer[] = "Anders Bjerin was here...";
  1274.  
  1275.  
  1276. /* Declare our functions: */
  1277. void main();
  1278. void clean_up( STRPTR text );
  1279.  
  1280.  
  1281. void main()
  1282. {
  1283.   /* Error number: */
  1284.   BYTE error;
  1285.   
  1286.   
  1287.   /* Get a reply port: (No name, priority 0) */
  1288.   replymp = (struct MsgPort *)
  1289.     CreatePort( NULL, 0 );
  1290.   if( !replymp )
  1291.     clean_up( "Could not create the reply port!" );
  1292.  
  1293.  
  1294.   /* Create the printer request block: */
  1295.   printer_req = (union printerIO *)
  1296.     CreateExtIO( replymp, sizeof(union printerIO) );
  1297.   if( !printer_req )
  1298.     clean_up( "Not enough memory for the printer request block!" );
  1299.  
  1300.  
  1301.   /* Open the Printer Device: */
  1302.   printer_dever = OpenDevice( "printer.device", 0, printer_req, 0 );
  1303.   if( printer_dever )
  1304.     clean_up( "Could not open the Printer Device!" );
  1305.  
  1306.  
  1307.  
  1308.   /* We want to print some text: (translated) */
  1309.   printer_req->ios.io_Command = CMD_WRITE;
  1310.  
  1311.   /* Give the start address of our data: */
  1312.   printer_req->ios.io_Data = (APTR) buffer;
  1313.  
  1314.   /* Set number of chracters that should be printed: */
  1315.   printer_req->ios.io_Length = 25;
  1316.  
  1317.   /* Do our request: */
  1318.   error = DoIO( printer_req );
  1319.  
  1320.   /* Check if the request was successfully executed: */
  1321.   if( error )
  1322.     printf( "Problems while printing!" );
  1323.  
  1324.  
  1325.   /* Clean up and quit: */
  1326.   clean_up( "The End!" );
  1327. }
  1328.  
  1329.  
  1330. /* Close and return everything that has been */
  1331. /* opened and allocated before we quit:      */
  1332.  
  1333. void clean_up( STRPTR text )
  1334. {
  1335.   /* Close the Printer Device: */ 
  1336.   if( !printer_dever )
  1337.     CloseDevice( printer_req );
  1338.  
  1339.   /* Deallocate the printer request block: */
  1340.   if( printer_req )
  1341.     DeleteExtIO( printer_req, sizeof(union printerIO) );
  1342.  
  1343.   /* Remove the replyport: */
  1344.   if( replymp )
  1345.     DeletePort( replymp);
  1346.  
  1347.   /* Print the message: */
  1348.   printf( "\n%s\n", text );
  1349.  
  1350.   /* Quit: */
  1351.   exit( 0 );
  1352. }
  1353.  
  1354.  
  1355. 9.4  OTHER USEFUL COMMANDS
  1356.  
  1357. There exist four more printer request commands that may
  1358. sometimes be useful:
  1359.  
  1360.   1. Flush, removes all queued requests.
  1361.   2. Reset, reinitializes the printer device.
  1362.   3. Start, restarts the printer communication.
  1363.   4. Stop, temporary stops the printer communication.
  1364.  
  1365.  
  1366.  
  1367. 9.4.1  FLUSH
  1368.  
  1369. If several requests are sent to the printer device they are
  1370. all queued on a FIFO (First In First Out) basis. The command
  1371. "CMD_FLUSH" can then be used to remove all these queued
  1372. commands. Here is an example:
  1373.  
  1374.   /* We want to remove all queued requests: */
  1375.   printer_req->ios.io_Command = CMD_FLUSH;
  1376.  
  1377.   /* Do our request: */
  1378.   error = DoIO( printer_req );
  1379.  
  1380.   /* OK? */
  1381.   if( error )
  1382.     printf( "Could not remove the queued requests!\n" );
  1383.  
  1384.  
  1385.  
  1386. 9.4.2  RESET
  1387.  
  1388. Send the command "CMD_RESET" to reset the printer device. All
  1389. commands that are queued to the device will be removed, the
  1390. command that is currently executed will be aborted, and all
  1391. printer flags are resetted. Here is an example:
  1392.  
  1393.   /* We want to reset the printer device: */
  1394.   printer_req->ios.io_Command = CMD_RESET;
  1395.  
  1396.   /* Do our request: */
  1397.   error = DoIO( printer_req );
  1398.  
  1399.   /* OK? */
  1400.   if( error )
  1401.     printf( "Could not reset the printer device!\n" );
  1402.  
  1403.  
  1404.  
  1405. 9.4.3  START
  1406.  
  1407. After you have stopped the printer communication by sending an
  1408. CMD_STOP command, you may want to start the communication again.
  1409. It is done by sending a CMD_START command. Here is an example:
  1410.  
  1411.   /* We want to start printer communication again: */
  1412.   printer_req->ios.io_Command = CMD_START;
  1413.  
  1414.   /* Do our request: */
  1415.   error = DoIO( printer_req );
  1416.  
  1417.   /* OK? */
  1418.   if( error )
  1419.     printf( "Could not restart the printer communication!\n" );
  1420.  
  1421.  
  1422.  
  1423. 9.4.4  STOP
  1424.  
  1425. To temporary stop all printer communication you send a CMD_STOP
  1426. command. The communication will then first start again when a
  1427. CMD_START command is broadcasted. Here is an example:
  1428.  
  1429.   /* We want to temporary stop all printer communication: */
  1430.   printer_req->ios.io_Command = CMD_STOP;
  1431.  
  1432.   /* Do our request: */
  1433.   error = DoIO( printer_req );
  1434.  
  1435.   /* OK? */
  1436.   if( error )
  1437.     printf( "Could not stop the printer communication!\n" );
  1438.  
  1439.  
  1440.  
  1441. 9.5  FUNCTIONS
  1442.  
  1443. DoIO()
  1444.  
  1445.   DoIO() is used to send requests to a device, and waits for it
  1446.   to be completed. While the program is waiting it is put to
  1447.   sleep so it will not waste any computer time. DoIO() will
  1448.   return first when the request have been completed or failed,
  1449.   and no message is therefore sent to the reply port.
  1450.  
  1451.   Synopsis: error = DoIO( req );
  1452.  
  1453.   error:    (long) DoIO() will return first when the request has
  1454.             been completed or something has failed. If the
  1455.             request was successfully completed zero is returned,
  1456.             else an error number is returned. What error number
  1457.             depends on which device was used.
  1458.  
  1459.   req:      (struct IORequest *) Pointer to the request you
  1460.             want to have executed.
  1461.  
  1462.  
  1463. SendIO()
  1464.  
  1465.   SendIO() is used to send requests to a device, but will
  1466.   return immediately without any delay. To check if the request
  1467.   have been completed use the CheckIO() function, or look
  1468.   at the request's reply port for any messages. Once the
  1469.   request has been completed you must remove the message at
  1470.   the reply port. (CheckIO() will not do it.) To remove a
  1471.   message use the function Remove(). Note that you may NOT
  1472.   close the device before all requests have been completed
  1473.   or aborted!
  1474.  
  1475.   Synopsis: SendIO( req )
  1476.  
  1477.   req:      (struct IORequest *) Pointer to the request you
  1478.             want to have executed.
  1479.  
  1480.  
  1481. CheckIO()
  1482.  
  1483.   CheckIO() is used to check if a previously started request
  1484.   has been completed. Note that this function will not remove
  1485.   the message at the reply port. This must be done with the
  1486.   Remove() function.
  1487.  
  1488.   Synopsis: ptr = CheckIO( req );
  1489.  
  1490.   ptr:      (long) CheckIO() will either return NULL if the
  1491.             request have not been completed or it will return a
  1492.             pointer to the request block.
  1493.  
  1494.   req:      (struct IORequest *) Pointer to the request you
  1495.             want to check.
  1496.  
  1497.  
  1498. WaitIO()
  1499.  
  1500.   WaitIO() will wait for the request to be completed, and while
  1501.   the program is waiting it is put to sleep so no computer time
  1502.   is wasted.
  1503.  
  1504.   Synopsis: error = WaitIO( req );
  1505.  
  1506.   error:    (long) WaitIO() will return first when the request,
  1507.             that has previously been sent, has been completed or
  1508.             something has failed. If the request was successfully
  1509.             completed zero is returned, else an error number is
  1510.             returned. What error number depends on which device
  1511.             was used.
  1512.  
  1513.   req:      (struct IORequest *) Pointer to the request you
  1514.             want to wait for to be completed. Note that the
  1515.             request must have already been sent to the device
  1516.             by either a SendIO() or BeginIO() function call.
  1517.  
  1518.  
  1519. AbortIO()
  1520.  
  1521.   AbortIO() will try to abort a previously started request. This
  1522.   function should be used sparsely since it does not look so
  1523.   good if you start a request and the try to stop it. (Better
  1524.   not start it at all.) However, it is easy, and can sometimes
  1525.   be very useful.
  1526.  
  1527.   A request that is aborted will have its io_Error field set
  1528.   to IOERR_ABORTED (defined in header file "exec/errors.h").
  1529.  
  1530.   Synopsis: AbortIO( req )
  1531.  
  1532.   req:      (struct IORequest *) Pointer to the request you
  1533.             want to abort.
  1534.  
  1535.  
  1536. CloseDevice()
  1537.  
  1538.   CloseDevice() will close a device. Note that you should NOT
  1539.   close the device before all started asynchronous requests
  1540.   have either been completed or aborted.
  1541.   
  1542.   Synopsis: CloseDevice( ioreq );
  1543.  
  1544.   ioreg:    (struct IORequest *) Pointer to the device's
  1545.             request block.
  1546.  
  1547.  
  1548. OpenDevice()
  1549.  
  1550.   OpenDevice() will try to open the specified device.
  1551.   
  1552.   Synopsis: error = OpenDevice( name, unit, req, flags );
  1553.  
  1554.   error:    (long) If OpenDevice() managed to open the device
  1555.             it returns 0, else an error number is returned.
  1556.  
  1557.   name:     (char *) Name of the device you want to open.
  1558.             The name of the printer device is
  1559.             "printer.device".
  1560.  
  1561.   unit:     (long) Set this field to 0.
  1562.  
  1563.   req:      (struct IORequest *) Pointer to an already
  1564.             initialized printerIO union.
  1565.  
  1566.   flags:    (long) Set this field to 0.
  1567.  
  1568.  
  1569.  
  1570. 9.6  COMMANDS
  1571.  
  1572. Here is a complete list of commands you may send to the
  1573. printer device. For full documentation se examples above.
  1574.  
  1575. The special printer device commands: (Defined in header file
  1576. "devices/printer.h")
  1577.  
  1578.   PRD_RAWWRITE   Send untranslated characters to the printer.
  1579.  
  1580.   PRD_PRTCOMMAND Send a printer command.
  1581.  
  1582.   PRD_DUMPRPORT  Print graphics. (Dump a RastPort to the
  1583.                  printer.)
  1584.  
  1585.  
  1586. The rest of the commands you may use are normal exec commands,
  1587. and are defined in header file "exec/io.h".
  1588.  
  1589.   CMD_RESET  Resets all parameters of the printer device.
  1590.   CMD_WRITE  Send data to the printer (through preferences).
  1591.   CMD_STOP   Temporary stops all printer communication.
  1592.   CMD_START  Restarts printer communication.
  1593.   CMD_FLUSH  Removes all queued requests.
  1594.  
  1595.  
  1596.  
  1597. 9.7  EXAMPLES
  1598.  
  1599. Example 1
  1600.   This program demonstrates how you can use the Printer
  1601.   Device to send (raw as well as translated) text to a
  1602.   printer.
  1603.  
  1604. Example 2
  1605.   This program demonstrates how you can use the Printer
  1606.   Device to send (raw as well as translated) text to a
  1607.   printer. However, instead of waiting for our request to
  1608.   be completed as in Example 1, we use asynchronous
  1609.   requests.
  1610.  
  1611. Example 3
  1612.   This program demonstrates how you can send printer commands to
  1613.   the Printer Device, which will translate these commands with
  1614.   help of Preferences, before they are sent to the printer.
  1615.  
  1616. Example 4
  1617.   This example demonstrates how you can print graphics.
  1618.   It will dump the workbench's Rastport to the printer.
  1619.  
  1620.