Urs-Jakob Rüetschi
uruetsch@geo.unizh.ch

PJL Quick Reference

PJL is the Printer Job Language, developed by HP. Some non-HP printers also understand some PJL. Other than page description languages like PostScript and PCL, PJL does not produce any marks on the paper. Instead, it can be used to configure the printer and print jobs.

Topics in this Quick Reference:
Command syntax
Universal Exit Language
Structure of print jobs
Environment
Information requests
Unsolicited status
Echo and comments
Print job example
A note about page counting

The original documentation by HP, the Printer Job Language Technical Reference Manual, is available online (PDF).

Command syntax

All PJL commands start with @PJL, followed by the command name, followed by optional arguments to the command, followed by an optional carriage return (ASCII CR, decimal 13), followed by a line feed (ASCII LF, decimal 10):

@PJL COMMAND [arguments] [<CR>] <LF>

An exception to this format is the UEL command.

Another exception is just a plain @PJL followed by a newline. This can be useful to add structure to large PJL jobs, but has no effect. Blank lines are not allowed.

Conventions: we write <ESC> for the ASCII code ESC (decimal 27, octal 33) and <FF> for an ASCII form feed code (decimal 12); the optional <CR> and mandatory <LF> that end lines of PJL are not indicated in the remainder of this text.

Case sensitivity: the prefix @PJL must be uppercase, the rest of a command is case-insensitive.

Universal Exit Language

A series of PJL commands to the printer must always start with the Universal Exit Language or UEL sequence. It tells the PJL-aware printer that what follows is PJL code and no longer whatever language was currently being sent to the printer. The UEL sequence is

<ESC>%-12345X

(remember: <ESC> = ASCII ESC = 27 dec = 33 oct).

Typically, a print job starts with the UEL, followed by a couple of PJL statements to adjust printer settings like duplex printing, followed by the actual print job, followed by another UEL to give control back to PJL.

In most examples that follow, the initial UEL is omitted.

Structure of print jobs

A "well-formed" PJL print job starts with a UEL that is immediately (no white space!) followed by @PJL, which may be the prefix of an actual command or just ends the line. Then comes a series of PJL commands to prepare the printer for the following job (in PCL or PostScript or any other language supported by the printer). Finally, there is another UEL followed by nothing, not even a newline.

The actual print job that eventually produces marks on the paper should be sandwiched between a JOB and an EOJ (end of job) command. The JOB command takes optional agrguments like a job name or a password (see the PJL spec).

@PJL JOB [NAME = "name"] [PASSWORD = number] [DISPLAY = "text"]
@PJL EOJ [NAME = "name"]

The optional job name is interesting for it is reported by USTATUS JOB messages!

Here's an example of a complete print job:

<ESC>%-12345X@PJL
@PJL JOB NAME = "My Job"
<ESC>%-12345X@PJL
@PJL ENTER LANGUAGE = POSTSCRIPT
%!PS
100 100 moveto
/Times findfont 12 scalefont setfont
(Hello, world!) show
showpage
<ESC>%-12345X@PJL EOJ
<ESC>%-12345X

If a UEL appears between a JOB/EOJ pair, then it is treated as a printer language reset, not as a PJL job boundary. This means, in particular, that the job page counter will not be reset by such a nested UEL.

In principle, there can be more than one print job in a PJL job, each embedded between JOB and UEL EOJ commands. Note that there are three UEL commands: the first starts the job, the second returns control back to PJL, and the last one ends the PJL job.

Setting the job language

Many printers understand more than one page description language. PostScript is probably the most widely used and understood on most high-end printers, PCL (printer control language) is the one developed by HP but also understood by many printers. Other languages exist, but are not as widespread.

@PJL ENTER LANGUAGE = language

Here language is typically one of PCL, POSTSCRIPT, or AUTO (auto detection of the language based on some heuristics).

Note that HP refers to the language as the personality.

The printing environment

Some aspects of the printer can be controlled by setting variables in the PJL "environment". These variables can also be read back or collectively reset to default values. Values get lost when the printer is turned off. Default values survive power cycling the printer.

@PJL SET var = value # set a variable
@PJL DEFAULT var = value # set default value
@PJL INQUIRE var # inquire the value of a variable
@PJL DINQUIRE var # inquire a default value
@PJL RESET # restore default values
@PJL INITIALIZE # restore factory default values

Useful variables include: PAPER (paper format, e.g., A4 or LETTER), COPIES (how many copies to print), ECONOMODE (ON or OFF), PERSONALITY (the page description language to expect, same values as in the ENTER LANGUAGE command), TIMEOUT (in seconds), LANG (language), etc.

Duplex printing

If the printer has a duplexer, it may be activated using PJL as follows:

long binding (like a book):

@PJL SET DUPLEX = ON
@PJL SET BINDING = LONGEDGE

short binding (like a calendar):

@PJL SET DUPLEX = ON
@PJL SET BINDING = SHORTEDGE

Information about the printer

We may also ask the printer to give us some information that is not part of the (modifyable) environment:

@PJL INFO category

Here category can be ID (printer model name), CONFIG, MEMORY, PAGECOUNT, STATUS, USTATUS (available ustatus categories), VARIABLES (available environment variables), and some other key words. Example:

@PJL INFO PAGECOUNT
@PJL INFO PAGECOUNT
PAGECOUNT=12345
<FF>

Note that some printers omit the "PAGECOUNT=" string.

Unsolicited status

We may ask the printer to send us "unsolicited" status messages about what the printer is doing ("asynchronous" would have been the better term, but never mind). These can be turned on

@PJL USTATUS category = ON
and off
@PJL USTATUS category = OFF
for these categories: DEVICE, JOB, and PAGE. Say
@PJL USTATUSOFF
to turn all unsolicited status messages off.

If the category DEVICE is set to VERBOSE (instead of ON), the printer reports errors in PJL commands.

Unsolicited status messages sent by the printer have the following format:

@PJL USTATUS category
status message, one or more lines
<FF>

Echo and Comment

There is a command that just echoes itself back and there is also a way of embedding comments in PJL statements:

@PJL ECHO stuff to echo back
@PJL COMMENT your comments

PJL ECHO commands are mainly useful to synchronise status information that the printer may sends!

Note that all output produced by PJL is preceded by the PJL command that generated the output. For example, the command @PJL ECHO Hello produces

@PJL ECHO Hello

Print job example

<ESC>%-12345X@PJL
@PJL ECHO 2005-04-28 08:07:06
@PJL USTATUS JOB = ON
@PJL USTATUS PAGE = ON
@PJL JOB NAME = "My Print Job"
<ESC>%-12345X@PJL
@PJL ENTER LANGUAGE = POSTSCRIPT
%!PS
/Courier findfont 18 scalefont setfont
100 100 moveto (Hello, world!) show
showpage
<ESC>%-12345X@PJL
@PJL EOJ NAME = "End of Example Job"
@PJL USTATUS JOB = OFF
@PJL USTATUS PAGE = OFF
<ESC>%-12345X

A note about page counting

PJL can be used for page-based accounting by exploiting the fact that the number of pages printed for a job is reported in the USTATUS JOB response to @PJL EOJ. For example, the print job above will react to the @PJL EOJ NAME = "End of Example Job" as follows:

@PJL USTATUS JOB
END
NAME="End of Example Job"
PAGES=n
<FF>

Because unsolicited messages arrive asynchronously, we have to make sure that we associate them with the proper print job. To this end, we could set the job name to a "cookie" value and check for it on arrival of USTATUS JOB messages.

(Addendum, early 2011: we've seen a Windows printer driver that produces PJL with unbalanced JOB/EOJ commands. This breaks proper page-conting!)

ujr/2005-04-23