                     PROGRAMMING WITH PRTSTR.DLL (5/15/93)
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Introduction:
~~~~~~~~~~~~~
   Paradox for Windows (PfW) ObjectPAL (OPAL) simply doesn't allow you to
   "take control" of your default Windows printer to output text strings
   directly to it, such as the DOS version of Paradox does.  Therefore, the
   following code is not valid:

     prtPrint("Hello Printer!", 1)

   ...until now that is!  VS Toolbox Software has now filled this gap in OPAL
   functionality with our new PrintString Windows DLL (PrtStr), designed
   expressly to meet the needs of Paradox for Windows application developers
   just like you.  If you were using PrtStr, the code snippet above would
   print "Hello Printer!" directly to your default Windows printer without your
   having to create a pre-defined PfW "Report"!


PrtStr Function Overview:
~~~~~~~~~~~~~~~~~~~~~~~~~
   This Shareware version of PrtStr allows a single instance of your Paradox
   for Windows application to call any of the following 8 functions:

      PrtOpen()................... Begins a new printjob
      PrtLines().................. Returns printer's # of lines per page
      PrtChars().................. Returns printer's # of chars per line
      PrtCurrLine()............... Returns the current line # on the page
      PrtPrint(String, SmallInt).. Prints String + SmallInt # of LineFeeds
      PrtLF(SmallInt)............. Prints SmallInt # of blank lines
      PrtFF()..................... Formfeed (starts a new page)
      PrtClose().................. Ends the current printjob


Paradox for Windows "Uses" Clause:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   The use of any DLL from within PfW, such as PRTSTR.DLL, requires that you
   create a "Uses" clause for the specific DLL and it's functions you want to
   make use of (call).  The PfW Form PRTSTR.FSL, included in this Shareware
   distribution package, provides you with an example of this required code,
   attached to a single button.  Where you locate your PrtStr Uses clause and
   associated calling code (Library, Script or Form) will depend on the
   "scope" you want PrtStr to have in your PfW application.  (Please refer to
   pages 45-53 of the OPAL Reference manual for more information about the
   Uses clause and pages 78-82 of the OPAL Developer's Guide for a discussion
   about Scope.)

   The Uses clause necessary for the Shareware version of PrtStr is:

      uses PRTSTR
	 PrtOpen() CWORD
	 PrtLines() CWORD
	 PrtChars() CWORD
	 PrtCurrLine() CWORD
	 PrtPrint(stringVar CPTR, siVar CWORD) CWORD
	 PrtLF(siVar CWORD) CWORD
	 PrtFF() CWORD
	 PrtClose() CWORD
      endUses

   NOTE: stringVar is declared as a String and siVar is declared as a SmallInt.

PrtOpen():
~~~~~~~~~~
   The PrtOpen function must be called to BEGIN each new printjob prior to
   calling any other PrtStr function.  PrtOpen does not take any parameters
   and returns a SmallInt value (we call it a Return Code).

   PrtOpen performs the following tasks:

      * Determines if the printer is already 'open'.
      * Obtains the current default Window's printer driver information.
      * Resets the PrtStr internal 'lines printed' counter to 0.
      * Initiates the Windows Print Manager program (if the printer is
	defined to use the 'Print Spooler').
      * Initiates a Windows Print Manager job.
      * Begins a new Windows 'print' document.
      * If any step fails, returns a negative return code, else it returns 0.


   Syntax example:  Print the words "Hello Printer!" to the printer...

      if PrtOpen() = 0 then
	 PrtPrint("Hello Printer!", 1)
	 PrtClose()
      else
	 msgInfo("PrtStr Error", "Printer Open failed")
      endif

PrtLines():
~~~~~~~~~~~
   The PrtLines function provides your application with the number of lines
   per page allowed by the current printer & page orientation.  This gives you
   an opportunity to code your own page-overflow code, if needed.  PrtLines
   does not take any parameters and returns a SmallInt value.

   NOTE: PrtPrint automatically generates a formfeed if it determines that
	 the next line to be printed would be off the bottom of the page.


   Syntax example:  Print a page footer at the bottom of every page...

      var
	 linesPerPage, currLineNo, loopCounter  SmallInt
	 textVar String
      endVar

      if PrtOpen() = 0 then                            ;open printer
	 linesPerPage = PrtLines()                     ;set lines per page
	 for loopCounter from 1 to 100                 ;begin a loop of 100
	    if PrtCurrLine() > (linesPerPage - 3) then ;page overflow?
	       PrtLF(1)                                ;1 linefeed
	       PrtPrint("Page Footer", 1)              ;print page footer
	       PrtFF()                                 ;formfeed
	    endIf
	    textVar = "Line # " + strVal(loopCounter)  ;build a String
	    PrtPrint(textVar, 1)                       ;print a line
	 endFor                                        ;end of loop
	 PrtClose()                                    ;close printer
      else
	 msgInfo("PrtStr Error", "Printer Open failed")
      endif


Character Widths & Line Counts:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   The following chart is provided for your convenience, as PrtLines and
   PrtChars provide printer and page orientation specific values to your
   program.  The printer font used by the Shareware version of PrtStr is the
   default Windows 'system' font.  This is a fixed-point (non-proportional)
   font, which then makes it easy for you to line up columns in your printout.

   If you use a printer other than one of those listed here, run the
   PRTSTR.FSL demo form and it will produce a report that shows you the values
   for your specific printer.

	      Printer     Orientation   Chars Wide   Lines Long
	     ~~~~~~~~~~   ~~~~~~~~~~~   ~~~~~~~~~~   ~~~~~~~~~~
	     HP LJII       Portrait         90           63
	     HP LJII       Landscape       115           48

	     Postscript    Portrait        105           76
	     Postscript    Landscape       139           57


PrtChars():
~~~~~~~~~~~
   The PrtChars function provides your application with the number of
   characters per line allowed by the current printer & page orientation.
   This gives you an opportunity to code a string-length-check so PrtStr
   won't automatically truncate your text string if it's too long.  PrtChars
   does not take any parameters and returns a SmallInt value.

   NOTE: PrtPrint automatically truncates your text value to the maximum
	 allowable line length specified by the printer and page orientation.


   Syntax example:  Print the number of characters per line allowed...

      var
	 textVar  String
      endVar

      if PrtOpen() = 0 then
	 textVar = "Characters per line = " + strVal(PrtChars())
	 PrtPrint(textVal, 1)
	 PrtClose()
      else
	 msgInfo("PrtStr Error", "Printer Open failed")
      endif


PrtCurrLine():
~~~~~~~~~~~~~~
   The PrtCurrLine function provides your application with the current line
   number of the page being printed.  Like PrtLines, this function gives you
   an opportunity to code your own page-overflow code, if needed.  PrtCurrLine
   does not take any parameters and returns a SmallInt value.


   Syntax example:  Print the current line number on the printout.
		    (For a more complex example, refer to PrtLines.)

      var
	 textVar  String
      endVar

      if PrtOpen() = 0 then
	 textVar = "Current print line = " + strVal(PrtCurrLine())
	 PrtPrint(textVal, 1)
	 PrtClose()
      else
	 msgInfo("PrtStr Error", "Printer Open failed")
      endif


PrtPrint(String, SmallInt):
~~~~~~~~~~~~~~~~~~~~~~~~~~~
   The PrtPrint function is the whole reason for the PrintString Windows DLL!
   This function is used to print any PfW/OPAL "string" that you can create.
   If you need to print any type of numerical value, you must first use OPAL's
   strVal() function to convert it to a string.  You may also use OPAL's
   format() function to build a pre-formatted string of text and numbers.

   Parameters to pass:
      String is a variable you declare as a String, or a literal text string,
      which contains the actual text you want to have printed.

      SmallInit is a variable you declare as a SmallInt, which contains the
      number of linefeeds to be performed after printing the text contained in
      textVar.  A value of 1 tells PrtPrint to add a carriage return/linefeed
      combination to your text.  If you want one or more blank lines printed
      after your text, then set the value of lines at 2 or greater.

   PrtPrint performs the following tasks, returning a SmallInt value:

      * Checks to make sure the printer is 'open'.

      * Checks to make sure the 'textVar' string passed to PrtStr actually
	contains data.  If not, nothing is done.

      * Checks to make sure the 'lines' integer passed to PrtStr is greater
	than 0.  If not, it is automatically set to 1.

      * Checks the length of the string to be printed.  If it's longer than
	allowed by the current printer and page orientation, it is truncated
	to the maximum line length allowed.

      * Checks the current line number.  If it's greater than the allowable
	number of lines per page for the current printer and page orientation,
	an automatic call to PrtFF is performed which generates a Formfeed and
	resets the current line number to 1.

      * If all checks are successful:
	* The contents of the textVal string are printed.
	* An automatic call to PrtLF is performed the number of times
	  specified via the value in 'SmallInt' (default = 1).
	* A code of 0 is returned to your program.

      * If any errors are encountered, a negative return code is returned.


   Syntax example:  Print text in two different ways...

      var
	 textVar  String
      endVar

      if PrtOpen() = 0 then
         textVar = "Hello printer, this is example text #1"     ;pre-defined
	 PrtPrint(textVal, 2)
         PrtPrint("Hello printer, this is example text #2", 1)  ;literal
	 PrtClose()
      else
	 msgInfo("PrtStr Error", "Printer Open failed")
      endif

PrtLF(SmallInt):
~~~~~~~~~~~~~~~~
   The PrtLF function generates a printer LineFeed which prints a blank line
   the number of times specified via the SmallInt variable.  This function is
   automatically called when PrtPrint() is executed so you don't need to call
   it in your code unless you want extra blank lines printed under specific
   circumstances within your program's control.

   PrtLF takes one parameter, SmallInt, which specifies the number of LineFeeds
   to be issued, and returns a SmallInt value.


   Syntax example:  If some condition is met, print 3 blank lines...

      if PrtOpen() = 0 then
	 if someConditionIsMet then  ;your own condition goes here
	    PrtLF(3)
	 endIf
	 PrtClose()
      else
	 msgInfo("PrtStr Error", "Printer Open failed")
      endif


PrtFF():
~~~~~~~~
   The PrtFF function generates a printer FormFeed.  PrtFF is called
   automatically by PrtPrint() if the page's current line number becomes
   greater than the allowable number of lines per page.

   PrtFF does not take any parameters, returns a SmallInt value and performs
   the following tasks:

      * Issues a FormFeed command to the printer.

	If a Formfeed could not be generated due to low memory or low disk
	drive space (unable to continue spooling the printjob):
	   * An automatic call to PrtClose is performed, which cancels
	     the printjob and resets the printer status to 'Closed'.
	   * A Windows message box is displayed to the user (in case they can
	     correct the low memory or disk space condition).
	   * A negative    return code is sent back to your program.

      * Resets the current line number to 1.

      * If all went well, a code of 0 is returned to your program.


   Syntax example:  If some condition is met, start a new page...

      if PrtOpen() = 0 then
	 if someConditionIsMet then  ;your own condition goes here
	    PrtFF()
	 endIf
	 PrtClose()
      else
	 msgInfo("PrtStr Error", "Printer Open failed")
      endif

PrtClose():
~~~~~~~~~~~
   The PrtClose function must be called to END each printjob started with
   PrtOpen.  If it's not called, your report will not be sent from the print
   spooler to the physical printer.  PrtClose does not take any parameters and
   returns a SmallInt value.

   PrtClose performs the following tasks:

      * Ends the current Windows print document.
      * Ejects the last page of the print document (calls PrtFF).
      * Terminates the Windows Print Manager job which releases it to print.
      * If it was the last print job, Windows closes the Print Manager.
      * Resets the internal Printer 'Open' status to 'Closed'.
      * Resets the current line number to 1.
      * If any step fails, returns a negative return code, else it returns 0.


   Syntax example:  Close the printer...

      If PrtOpen() = 0 then
	 PrtPrint("Goodbye printer...", 1)
	 PrtClose()
      else
	 msgInfo("PrtStr Error", "Printer Open failed")
      endIf

PrtStr 'Return Codes':
~~~~~~~~~~~~~~~~~~~~~~
   Each of the PrtStr functions returns a SmallInt value (CWORD), which is
   referred to as the "return code", to let you know of it's success or
   failure.  The return codes are:

       0 = Successful - no further action required.
      -1 = Printer already open - printjob currently in progress.
      -2 = Unable to process a FormFeed request.  Printer is now 'Closed'.
      -3 = Unable to 'Open' a new printjob.  Printer is now 'Closed'.
      -4 = Unable to 'Start' a new printjob.  Printer is now 'Closed'.
      -5 = Printer is not currently 'Open'.
     *-6 = Low disk space encountered by spooler.  Printer is now 'Closed'.
     *-7 = Low memory encountered by spooler.  Printer is now 'Closed'.

   * This error will result in a Windows MessageBox being displayed to the
     user, since it may be the result of low memory or low disk space, which
     you might not be able to plan for in your application, but the user might
     be able to fix and re-run the requested job.


Using PrtStr Return Codes:
~~~~~~~~~~~~~~~~~~~~~~~~~~
   A typical printout to be generated by PrtStr function calls from within a
   pushButton method might look something like the example on the following
   pages.  (NOTE:  A more complete example is provided 'live' in the
   un-delivered PRTSTR.FSL form included in this Shareware distribution
   package.)

   It is suggested that you use this return-code checking method of calling
   PrtStr functions to begin each new report.  Once you are certain that the
   results are what you expect, you can start replacing code.  The one return
   code check which should ALWAYS be performed is PrtOpen.  If PrtStr cannot
   open the printer, all subsequent function calls will fail.


   Syntax Example:  pushButton method to print "Hello Printer!" and display
		    PrtStr errors if any are encountered...


;Define variables global to this method...
var
   errMsg                  String
   rtnCode                 SmallInt
endvar


;Define the error-handling, on-screen display proc...
proc PrtStrError()
   switch
      case rtnCode = -1 : errMsg = "Printer already 'Open'."

      case rtnCode = -2 : errMsg = "Unable to process a FormFeed.\n"
				 + "Printer is Closed."

      case rtnCode = -3 : errMsg = "Unable to 'Open' a new printjob.\n"
				 + "Printer is Closed."

      case rtnCode = -4 : errMsg = "Unable to 'Start' a new printjob.\n"
				 + "Printer is Closed."

      case rtnCode = -5 : errMsg = "Printer is not 'Open'."

      case rtnCode = -6 : errMsg = "Print spooler reported low disk space.\n"
				 + "Printjob cancelled. Printer is Closed."

      case rtnCode = -7 : errMsg = "Print spooler reported low memory.\n"
				 + "Printjob cancelled. Printer is Closed."

      otherwise         : errMsg = "Unknown error returned from PrtStr."
   endswitch

   msgInfo("PrtStr DLL Error", errMsg)
endProc


;(Start of the actual pushButton method code...)
method pushButton(var eventInfo Event)
;Open the printer...
   rtnCode = PrtOpen()  ; this gives you a 'return code' you can validate

;Check for errors...
   if rtnCode < 0 then
      PrtStrError()
      return
   endif


;Print a line of text...<<to make this fail, comment out the PrtOpen stmt>>
   rtnCode = PrtPrint("Hello Printer!", 1)
   if rtnCode < 0 then
      PrtStrError()
      return
   endif


;Close the printer
   rtnCode = PrtClose()
   if rtnCode < 0 then
      PrtStrError()
      return
   else
      msgInfo("Message from PrtStr DLL", "Printjob now completed.")
   endif

endmethod
