Skip to main content
Skip table of contents

Why setstdio is needed

This page applies to Harlequin v13.1r0 and later; both Harlequin Core and Harlequin MultiRIP.

Why not use %terminal% directly? There are three reasons:

  • The print operator, and procedures which use it (such as ==), direct their output to %stdout% by definition; setstdio allows this output to be re-routed.
  • Predefined fragments of the PostScript language and some built-in operators automatically use %stdin%, %stdout%, and %stderr% as their input and output channels. For example, the executive always reads from standard input, and the default error handlers (which you could of course redefine—but so could an application) write their messages to %stdout% using the print operator.
  • The Apple LaserWriter and other simple printers read their PostScript-language jobs from %stdin% —indeed this may be the only input “device” such a printer knows about. Unfortunately, some PostScript-language producing applications make assumptions that rely on this behavior.

In the last case, an application might write, for example:

TEXT
/infile (%stdin%) (r) file def
/str 512 string def
...
{ infile str readstring pop } image
... image data ...

when it should correctly (and more simply) write1 :

TEXT
/str 512 string def
...
{ currentfile str readstring pop } image
... image data ...

Therefore, unless you are certain that the PostScript language to be executed does not make this mistake, you should not write:

TEXT
(%disk0%image.ps) run

Instead, write something like this:

TEXT
(%disk0%image.ps) (r) file dup (%console%) (w) file
statusdict /setstdio get exec cvx exec % the input file

Recall that run is simply a shortcut for (r) file cvx exec. If the stream of PostScript being executed to do this is not part of a procedure, you may need a save and restore to reinstate the previous associations of %stdin% and %stdout% to continue executing your PostScript when the file is complete.

1. It is not relevant to the point being made, but for greater efficiency (which is often very important when processing images) the line with the procedure is better written:

{ currentfile //str readstring pop } bind image

or better still, use currentfile as a direct DataSource in the Level 2 dictionary form of the image operator. The examples are, however, typical of actual applications.

So defineresource for an externally defined filter looks like this:

filtername dict /Filter defineresource

where filtername is a name object identifying the filter type, and dict is a dictionary containing keys that identify the implementation of the filter, as described below; defineresource returns filtername as its result in this case.

Where the filter is coded in a plugin, the filtername must correspond to the name of the channel class which implements the filter. Core-RIP implementations can use any name. To override a built-in filter, the name must be that of the built-in filter, which means that the channel class name must also have this name as listed in Table 3.6 in [RB2]. In other cases, we recommend using your OEM name or number as part of the filter name to ensure uniqueness.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.