[comp.lang.postscript] A useful def for self-contained packages

cosell@bbn.com (Bernie Cosell) (06/10/90)

Well, another round of debugging of bbfig uncovered a fairly subtle problem
when writing an independent library-like package that is intended to be
loaded with arbitrary other packages.  We all know enough to put all of our
<def>'s in a private-to-the-module dictionary and be very careful to <begin>
that dictionary.  Well, I just got through with an embarrassingly difficult
debugging of a problem with bbfig: that of getting systemdict things
redefined.  I was trying to bbfig a small file that had the not-unreasonable
definitions:

    /mt /moveto load def
    /lt /lineto load def

innocent enough... but wait: "lt" is already defined as something else!!
Whoops... all of a sudden "a b lt { whatever } if" doesn't do quite the right
thing any more...  Clearly a 'bind' when your package is first loaded is what
is necessary, but it is at best awkward, and in the limit impossible, simply
to have all of your <def>s turn into <bind def>s.

Well, the following is a snippet which I had buried in the trace
package I posted a while back, but this is a useful and necessary
enough function that I think it is worth calling out as a useful 'tool'
to have on its your in the standard bag of tricks.  What you do is
write your file just as you normally would --- putting the <def>s
freely in any order you choose.  But also include a <def> for this:

% key binddefinition - ; this will do a 'bind' on the procedure given by 'key'
/binddefinition
{
    dup where
    {
	exch
	2 copy
        get bind put
    } 
    { undefined } ifelse
} def


Then, at the very end of your file, make the dict-stack be the way you want
it to be (typically this just means doing a "moduledict begin"), and put in a
sequence of
   /firstdef binddefinition
   /secondef binddefinition
   ...etc
and that'll fix everything so that your module is cleanly freed of the
randomnesses that the user might foist on you by the time your package gets
called.

  /Bernie\

zben@umd5.umd.edu (Ben Cranston) (06/12/90)

I am in the midst of trying to write "the canonical gray letters diagonally
across each page, like DRAFT" postscript program, and stumbled across a real
hairy gotcha.  Thought I would share the problem and solution.

Suppose you want to redefine the meaning of a PostScript verb, but keep access
to the old definition.  For example, you want to redefine showpage to impose
a landscape coordinate system upon each new page.  You can do something like:

/showpage [
    /showpage load
    611.76 0 /translate load 90 /rotate load
] cvx def

this works because "showpage" is an OPERATOR and will be executed when the
interpreter comes across it in the procedure array.  But note well: this kind
of redefinition will only work ONCE because "showpage", after the above, is
a PROCEDURE (array) not an OPERATOR.  One could follow this with:

/showpage [
    /showpage load /exec load
    /otherproc load /exec load
] cvx def

Now, running across showpage merely puts it on the stack, and the exec that
follows it actually runs it.  But, this scheme won't work with the original
OPERATOR showpage because it gets run immediately and the exec dies off with
an empty-stack diagnostic.

This is the only way I've been able to make it work for both cases:

/showpage [
    /showpage load dup type (operatortype) ne {/exec load} if
    /otherproc load /exec load
] cvx def

I'll post the "gray letters diagonally" program later this week, and I'd like
to have some beta testers with weird postscript environments, like the "n-up"
routines that put multiple logical pages on a physical page.  Since I'm using
the "clippath pathbbox" trick for finding the physical page size this beast
should be physical-page-size independant.

It has worked fine for both portrait and landscape anyway...
-- 

"It's all about Power, it's all about Control
 All the rest is lies for the credulous"
-- Man-in-the-street interview in Romania one week after Ceaucescu execution.

woody@chinacat.Unicom.COM (Woody Baker @ Eagle Signal) (06/12/90)

In article <6656@umd5.umd.edu>, zben@umd5.umd.edu (Ben Cranston) writes:
> I am in the midst of trying to write "the canonical gray letters diagonally
> across each page, like DRAFT" postscript program, and stumbled across a real
> hairy gotcha.  Thought I would share the problem and solution.
> 
> Suppose you want to redefine the meaning of a PostScript verb, but keep access
> to the old definition.  For example, you want to redefine showpage to impose
> a landscape coordinate system upon each new page.  You can do something like:
> 
> /showpage [
>     /showpage load
>     611.76 0 /translate load 90 /rotate load
> ] cvx def
> 

Here is how I did it....

currentdict
/*moveto known not
	{
	/*moveto /moveto load def
	} if
	

/moveto
	{
	disableflag 1 eq
		{
		*moveto	% do original moveto
		}
		{
		% anything you want
		} ifelse
	} def

In my application, disableflag was used to enable and disable the
operation of the original showpage operator.  It worked well.

from Don Lancasters laserwriter column #31, is a nice little
gray stamp on the page routine.  Note, This is copied as he wrote it.
I do not condone this kind of coding.

100 dict /workdict exch def workdict begin %MUST be out of userdict

/printtimestuff {save /pts exch def mark /Helvetica-Bold findfont 
[80 0 0 80 0 0] makefont setfont /msg (FILE COPY) def 0 setlinewidth 1
setlinejoin 1 setlinecap 170 240 translate 45 rotate 0 0 moveto /strrx 
(X) def msgt {strrx exch 0 exch put strrx true charpath current point stroke
newpath moveto }forall cleartomark pts restore } def

/showpage {printtimestuff systemdict /showpage get cvx exec} def

% all of your normal stuff goes here

showpage

This routine prints out a gray line FILE COPY across the page.  I hope
I didn't make any typos.

Cheers
Woody