The paint system achieves device independence by separating the
application code from the device dependent code as follow:

The application code calls routines in the interface library (see
Interface/applib).  These routines communicate with a device driver
program via unix pipes, parent to child. The driver consists of device
dependent code loaded with the interface routine paint_interface() (see
Interface/driverlib) that knows how to talk to the application
program.

Source code directories:

  Interface: this directory contains the source code for the
	     interface.  Both the application and driver libraries
	     are found here.

  Drivers:   this directory contains directories for each driver
	     supported by paint. These directories contain the
	     C routines which are required by the interface and
	     a shell script which sets the necessary device driver
	     parameters and calls the real driver.

The interface, consisting of the application library and the
driver library, is defined as follows:

application library (applib.a) has the following routines:

    Pconnect()

     Must be the first routine called by an application.  Executes the
     driver shell (as specified by the unix environment variable
     PAINT_DRIVER, which must be a full path reference) and opens a two
     way pipe to this process.  The application program uses these
     pipes to talk to the driver, which in turn uses stdin and stdout
     to talk to the application program.

    Pdisconnect()

     Must be the last routine called by an application.  Sends a close
     request to the driver and closes the communication pipes to the
     driver.

    Popen()

     If application intends actually send output to the printer,
     this routine must be called after the call to Pconnect().
     If the application only needs to know the number of colors, or the
     other configuration parameters fo the printer, Popen() need not
     be called.
    
    Pclose()

     If Popen() was called, this routine must be closed to flush any output
     to the printce. This should be called just before Pdisconnect().
     If Popen() was not called, Pclose() should NOT be called.

    double Phres()

     Returns the horizontal resolution of the device in pixels per
     inch.

    double Pvres()

     Returns the vertical resolution of the device in pixels per inch.

    Pnpixels()

     Returns the number of pixels in the horizontal
     (No limit is assumed in the vertical)

    Pncolors()

     Number of colors available. currently this routine
     should never return a number larger than 256.

    Pnchars()

     Returns the number of characters in the horizontal

    Palpha()

     Puts the printer in alpha-numeric (ie, text) mode.
     Should be called once before call to Ptext().

    Ptext(s)
     char *s;

     Prints the text s on the printer.  Assumes one text string per
     line.  The text itself should not have any non-printing characters
     (eg. linefeeds, tabs, or newlines) and the driver is free to
     discard any such characters.  The driver can append as many
     newlines as required to effect the printing.

    Praster()

     Puts the printer in raster (ie, graphic) mode.
     Should be called once before each Ppictsize() call.

    Ppictsize (nrows, ncols)

     Sends size of picture to be drawn to driver.
     Should be called before any raster data is sent to the driver.

    Pdata_begin()

     Indicates one line of raster data to begin.

    Pdata (buf, n)
     unsigned char *buf;
     int n;

     Sends n bytes of data starting at buf to driver.  Repeated calls
     to Pdata() can be made between calls to Pdata_begin() and
     Pdata_end() with exactly ncols of data as specified in the the
     call to Ppictsize().

    Pdata_end()

     Ends one line of raster data
     It is important that exactly ncols of data be sent before
     this call is made.

    Prle_begin()

     Indicates one line of run-length-encoded raster data to begin.

    Prle (value, n)
     unsigned char value;
     int n;

     Sends rle value n times to driver.
     Repeated calls to Prle() can be made as long as exactly ncols of
     data are sent.

    Prle_end()

     Ends of line of rle raster data.

    Pcolornum (red, grn, blu)
     float red, grn, blu;

     Returns the color number (according to the predefined color table)
     for the color specified by the red, grn, blu intensity percentages.

    Pcolorvalue (n, red, grn, blu)
     int n;
     float *red, *grn, *blu;

     Computes the red, grn, and blu components of the predefined
     color n.
    
    Ptranslate_colors (red, grn, blu, table, n)
     unsigned char *red, *grn, *blu;
     unsigned char *table;

     Translates the colors (red,grn,blu) which are in the range (0-255)
     into corresponding printer color numbers and stores them in table

The driver interface requires the writing of the following
routines for each driver to be implemented:

    Popen (device)
     char *device;

     Open the printer on "device" for output, and perform
     whatever intialization is required by the printer.
     Load the predefined color table.

    Pclose()

     Flush pending output to the printer and close the device.

    Pflush()

     Flush pending output to the printer.

    Palpha()

     Put printer in alpha-numeric mode (ie, text mode)

    Ptext (s)
     char *s;

     Print string s on printer. Non-printing characters can be
     ignored or suppressed. Linefeed or newlines should be
     appending as necessary (at least one).

    Praster()

     Put printer is raster (ie, graphics) mode.

    Ppictsize (nrows, ncols)

     Prepare printer for a picture with nrows and ncols.

    Pdata (buf, n)
     unsigned char *buf;
     int n;

     Output the raster data in buf. n will be ncols as specified
     in Ppictsize.

    Prle (buf, n)
     unsigned char *buf;
     int n;

     Output the run-length-encoded raster data in buf.
     The data is in pairs: value,repeat
     where repeat can be 0-255, with 0 meaning 256.
     n will be the number of pairs.  (Of course the
     n repeat counts had better add up to ncols.
     The interface should check this, just to be nice).

    Pncolors()

     Number of colors available. currently this routine
     should never return a number larger than 256.

    Pcolornum (red, grn, blu)
     float red, grn, blu;

     Returns the color number (according to the predefined color table)
     for the color specified by the red, grn, blu intensity percentages.

    Pcolorvalue (n, red, grn, blu)
     int n;
     float *red, *grn, *blu;

     Computes the red, grn, and blu components of the predefined
     color n.

A main() must be written which looks like:

	main(argc,argv) char *argv[];
	{
	    paint_interface(argc,argv);
	}

This main() must then be linked with the routines describes above and
the driverlib.a to form the driver program.

How the user selects the printer.

   The user selects the printer by setting the grass envirnoment variable
   PAINTER to a driver name. This is done using the p.select command.

How the application program starts the driver.

   The Pconnect() call runs the command

	$GISBASE/etc/paint/driver.shell $PAINTER
    
   which sets some unix environement variables and runs the shell
   script

       $GISBASE/etc/paint/driver.sh/$PAINTER

   This shell script must be written by the driver writer. It is
   responsible for setting some other unix env variables (described
   below) and then running the driver program which is named

	$GISBASE/etc/paint/driver/$PAINTER


   The driver shell script must set the following unix env variables

   HRES=     horizontal resolution, pixels per inch
   VRES=     vertical resolution, pixels per inch
   NPIXELS=  number of pixels in the horizontal
   NCHARS=   number of alpha-numeric characters in the horizontal
   MAPLP=    output port (eg, /dev/tty1)

   also, if the driver is on a different machine than the application
   program (eg, using rsh to run the driver), and the two machines
   do not have the same integer format, then the following parameter
   must also be set

   TRANSPARENT=y    integers should be sent in ascii instead of binary
