                   "Green-bar" paper on a LaserJet II
                   ----------------------------------

This document explains how to shade every other line of a LaserJet
II-printed report so that the result is similar to that produced on
"green bar" paper stock.  This makes it easier to read reports such as
data file listings, etc., where each line is a record.


Printer functions required
--------------------------
The technique involves two basic LJ functions: cursor positioning and
rectangular area filling.  These are documented in the "LaserJet Series
II Printer Technical Reference Manual", available at extra cost from
Hewlett-Packard (Part No. 33440-90905).

The area filling functions allow you to define a rectangular box and
fill it with the pattern or shading level of your choice.  We will use a
box that is 8.5" wide and 1/6" high--the full width of the paper by one
line high.  It is then "filled" by shading.

The cursor positioning functions move the "cursor", which is the active
printing location--where the next character will print.  It is analagous
to a screen cursor.  In essence, we will start at the upper left corner
of the page and shade every other line by moving the cursor down two
lines after each fill.


Algorithm
---------
The basic algorithm is:

    Save the "cursor" position
    Move the cursor to the upper left corner of the page
    Define the box characteristics
    Do 30 times
        Shade the box
        Move the cursor down two lines
    End do
    Restore the initial cursor position

At the end of this process, every other line has been shaded.  The
character data is then sent to the printer as usual for printing.


Specific functions used
-----------------------
"Ec" is an ASCII ESC character (decimal code 27, hex 1B).  "#" is a
variable value that is replaced by a numeric parameter (in ASCII: for
example, "50" is transmitted by sending the ASCII characters "5" and
"0").

Note: the LJ-II commands show below have been simplified somewhat, i.e.,
the definitions shown don't necessarily convey all possible formats of
the commands given.

1. Cursor positioning

    a. Save/restore cursor position

            Ec&f0S

       This saves the current cursor position by pushing it onto a LIFO
       stack.  It can be restored (popped) by the control string

            Ec&f1S

        The stack is large enough to save 20 cursor positions.

    b. Set cursor position (horizontal absolute, by dots)

            Ec*p#X

       The variable value # is the horizontal dot number.  The
       leftmost dot on a row is dot 0, so the control string

            Ec*p0X

       moves the cursor to the left side of the page.

    c. Set cursor position (vertical absolute, by dots)

            Ec*p#Y

       The variable value # is the vertical dot number.  The topmost
       dot row on the page is row 0.  To put the cursor at the top of
       the page:

            Ec*p0Y

    d. Set cursor position (vertical relative, by rows)

            Ec&a#R

       The variable value is preceded by a plus or minus sign to
       indicate whether the cursor is to be moved up (-) or down (+) the
       specified number of rows.  This moves the cursor down two rows:

            Ec&a+2R


2. Area filling

    a. Define box width (in dots)

            Ec*c#A

       To define a box 8.5" wide (8.5 x 300 = 2550 dots):

            Ec*c2550A

        Note that the printer will clip the box at the left and right
        margins.

    b. Define box height (in dots)

            Ec*c#B

       To define a box 1/6" (one line) high:

            Ec*c50B

        1/6" at 300 dots per inch is 50 dots.

    c. Define shading level

            Ec*c#G

        The variable value # represents a shading level from 2% to 100%.
        The printer can actually print eight different levels, and there
        are some discrepancies in the HP manual regarding these levels.
        However, 2, 10, 15, 30, 45, 70, 90, and 100% would seem to
        represent the real levels.  To set 15% shading:

            Ec*c15G

        I suggest 10% or 15% shading for the "green bar" paper.

    d. Print box as currently defined

            Ec*c2P

       This control string performs the gray scale fill using the area
       dimensions and fill level currently defined.  The box is printed
       at the current cursor position; the cursor position is not
       changed.  As always, no physical printing occurs until the page
       is filled with text data or a formfeed is received.


Combining functions
-------------------
The LJ-II allows some concatenation of control strings.  Strings may be
concatenated if the first two characters following the ESC are the same:

        Ec*p#X
        Ec*p#Y

If strings are combined, the trailing character for all control
strings except the last one is lowercase, and the first three characters
are omitted after the first string.  For example, the three strings

        Ec*c2550A
        Ec*c50B
        Ec*c15G

can be combined into one string as follows:

        Ec*c2550a50b15G


Margins etc.
------------
This document assumes that you're using 8.5 x 11 paper at 60 lines per
page (i.e., with the default top and bottom margins), six lines per
inch, in portrait mode.  If you use anything else, you'll need to adjust
some of the parameters.

The left/right margins have no effect on the printing of the shaded
rectangles, but the top margin and text length do.  In other words, dot
column 0 is an absolute position on the page, but dot row 0 is relative
to the top margin.  If you print shaded boxes beyond the bottom of the
text area, a page eject will occur (and you'll have a shaded page
with no text).


Sample code
-----------
Each of the following code samples sends the following control sequences
to the printer:

    Ec&f0S                  ; Save curpos
    Ec*p0x0Y                ; Cursor to (0,0)
    Ec*c2550a50b10G         ; Define box: 8.5" x 1/6", 10% shading
    (30 times:)
        Ec*c2P              ; Print box
        Ec&a+2R             ; Move down two lines
    Ec&f1S                  ; Restore curpos

Some of these have been combined for greater efficiency.

This code must be executed for each page printed, of course.  If you are
going to be printing many pages, it may be faster (especially in dBASE!)
to contatenate 30 instances of Ec*c2PEc&a+2R into one string (and print
it once per page) than to send the string to the printer thirty times
for each page.


BASIC:
    100 EC$ = CHR$(27)
    110 LPRINT EC$ + "&f0S" + EC$ + "*p0x0Y" + EC$ + "*c2550a50b10G";
    120 FOR I = 1 TO 30: LPRINT EC$ + "*c2P" + EC$ + "&a+2R";: NEXT
    130 LPRINT EC$ + "&f1S";

C:
    int i;
    fprintf (stdprn, "\033&f0S\033*p0x0Y\033*c2550a50b10G");
    for (i=1; i <= 30; i++)
        fprintf (stdprn, "\033*c2P\033&a+2R");
    fprintf (stdprn, "\033&f1S");

dBASE III+:
    set print on
    set console off
    Ec = chr(27)
    ?? Ec + "&f0S" + Ec + "*p0x0Y" + Ec + "*c2550a50b10G"
    i = 1
    do while i <= 30
        ?? Ec + "*c2P" + Ec + "&a+2R"
        i = i+1
    enddo
    ?? Ec + "&f1S"
    set print off
    set console on

dBASE IV:
    ??? "{ESC}&f0S{ESC}*p0x0Y{ESC}*c2550a50b10G"
    i = 1
    do while i <= 30
        ??? "{ESC}*c2P{ESC}&a+2R"
        i = i+1
    enddo
    ??? "{ESC}&f1S"

REXX:
    Ec = '1B'x
    call charout 'prn',Ec'&f0S'Ec'*p0x0Y'Ec'*c2550a50b10G'
    do 30
        call charout 'prn',Ec'*c2P'Ec'&a+2R'
    end
    call charout 'prn',Ec'&f1S'


            ===============================================

                              Document by:
                             Chris Dunford
                        The Cove Software Group
                              PO Box 1072
                           Columbia, MD 21044
                              301/992-9371
                         CompuServe 76703,2002

                             Prepared for:
                           CompuServe IBMNET
                                02/01/89
