1
% Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved.
3
% This software is provided AS-IS with no warranty, either express or
6
% This software is distributed under license and may not be copied,
7
% modified or distributed except as expressly authorized under the terms
8
% of the license contained in the file LICENSE in this distribution.
10
% For more information about licensing, please refer to
11
% http://www.ghostscript.com/licensing/. For information on
12
% commercial licensing, go to http://www.artifex.com/licensing/ or
13
% contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
% San Rafael, CA 94903, U.S.A., +1(415)492-9861.
16
% $Id: gs_setpd.ps 9350 2009-01-13 18:38:37Z ray $
17
% The current implementation of setpagedevice has the following limitations:
18
% - It doesn't attempt to "interact with the user" for Policy = 2.
20
languagelevel 1 .setlanguagelevel
23
% ---------------- Redefinitions ---------------- %
25
% Redefine .beginpage and .endpage so that they call BeginPage and
26
% EndPage respectively if appropriate.
28
% We have to guard against the BeginPage procedure not popping its operand.
29
% This is really stupid, but the Genoa CET does it.
30
/.beginpage { % - .beginpage -
31
.currentshowpagecount {
32
.currentpagedevice pop
33
dup //null ne { /BeginPage .knownget } { pop //false } ifelse {
34
% Stack: ... pagecount proc
36
% Stack: ... ..???.. oldcount
37
count 1 add exch sub { pop } repeat
44
% Guard similarly against EndPage not popping its operand.
45
/.endpage { % <reason> .endpage <print_bool>
46
.currentshowpagecount {
47
1 index .currentpagedevice pop
48
dup //null ne { /EndPage .knownget } { pop //false } ifelse {
49
% Stack: ... reason pagecount reason proc
51
% Stack: ... ..???.. print oldcount
52
count 2 add exch sub { exch pop } repeat
61
% Define interpreter callouts for handling gstate-saving operators,
62
% to make sure that they create a page device dictionary for use by
63
% the corresponding gstate-restoring operator.
64
% We'd really like to avoid the cost of doing this, but we don't see how.
65
% The names %gsavepagedevice, %savepagedevice, %gstatepagedevice,
66
% %copygstatepagedevice, and %currentgstatepagedevice are known to the
69
(%gsavepagedevice) cvn
70
{ currentpagedevice pop gsave
74
{ currentpagedevice pop save
77
(%gstatepagedevice) cvn
78
{ currentpagedevice pop gstate
81
(%copygstatepagedevice) cvn
82
{ currentpagedevice pop copy
85
(%currentgstatepagedevice) cvn
86
{ currentpagedevice pop currentgstate
89
% Define interpreter callouts for handling gstate-restoring operators
90
% when the current page device needs to be changed.
91
% The names %grestorepagedevice, %grestoreallpagedevice,
92
% %restorepagedevice, %restore1pagedevice, and %setgstatepagedevice
93
% are known to the interpreter.
96
{ % Since setpagedevice doesn't create new device objects,
97
% we must (carefully) reinstall the old parameters in
99
.currentpagedevice pop //null currentdevice //null .trysetparams
100
dup type /booleantype eq
102
{ % This should never happen!
103
SETPDDEBUG { (Error in .trysetparams!) = pstack flush } if
104
cleartomark pop pop pop
105
/.installpagedevice cvx /rangecheck signalerror
108
% A careful reading of the Red Book reveals that an erasepage
109
% should occur, but *not* an initgraphics.
113
/.uninstallpagedevice
114
{ 2 .endpage { .currentnumcopies //false .outputpage } if
118
(%grestorepagedevice) cvn
119
{ .uninstallpagedevice grestore .installpagedevice
122
(%grestoreallpagedevice) cvn
123
{ .uninstallpagedevice grestore .installpagedevice grestoreall
126
(%restore1pagedevice) cvn
127
{ .uninstallpagedevice grestore .installpagedevice restore
130
(%restorepagedevice) cvn
131
{ .uninstallpagedevice restore .installpagedevice
134
(%setgstatepagedevice) cvn
135
{ .uninstallpagedevice setgstate .installpagedevice
138
% Redefine .currentnumcopies so it consults the NumCopies device parameter.
141
.dicttomark readonly def
144
{ currentdevice //.numcopiesdict .getdeviceparams
145
dup type /integertype eq
146
{ exch pop exch pop }
147
{ cleartomark #copies }
151
% Redefine .currentpagedevice and .setpagedevice so they convert between
152
% null and a fixed empty directionary.
153
/.nullpagedevice 0 dict readonly def
154
/.currentpagedevice {
155
//.currentpagedevice exch dup //null eq { pop //.nullpagedevice } if exch
158
dup //.nullpagedevice eq { pop //null } if //.setpagedevice
161
% ---------------- Auxiliary definitions ---------------- %
163
% Define the required attributes of all page devices, and their default values.
164
% We don't include attributes such as .MediaSize, which all devices
165
% are guaranteed to supply on their own.
166
/.defaultpolicies mark
167
% M. Sweet, Easy Software Products
169
% Due to the fact that it is not possible to properly implement
170
% the selection policies from a Ghostscript driver, we have changed
171
% the default policy to "7" (impose) to avoid numerous problems with
172
% printing within CUPS...
182
dup /.LockSafetyParams known {
183
% Only possible error is invalidaccess
184
/setpagedevice .systemvar /invalidaccess signalerror
189
.dicttomark readonly def
190
% Note that the values of .requiredattrs are executed, not just fetched.
192
/PageDeviceName //null
193
/PageOffset [0 0] readonly
194
% We populate InputAttributes with all of the known page sizes
195
% followed by a dummy media type that handles pages of any size.
196
% This will create some duplicates, but that only slightly slows
197
% down the media selection (loop is in zmedia2.c).
199
% Some PostScript creators assume that slot 0 is the default media
200
% size and some can't handle a non-standard 4-element array which
201
% is a 'range' type page size (always put last).
203
% Real Devices that can only handle specific page sizes will override this.
206
% First put the device's default page size in slot 0
207
% This satifies those that have devices built with a4 as the default
208
0 mark /PageSize currentdevice /PageSize gsgetdeviceprop .dicttomark
209
statusdict /.pagetypenames get {
210
counttomark 1 sub 2 idiv exch mark exch /PageSize exch
211
% stack: mark --dict-- --dict-- ... key mark /PageSize pagetypename
212
% see note above about pagetype executable array contents.
213
load dup 0 get exch 1 get 2 array astore .dicttomark
215
% If NORANGEPAGESIZE is defined, (-dNORANGEPAGESIZE), then don't add
216
% the 'match any' PageSize entry
217
systemdict /NORANGEPAGESIZE known not {
218
% Add one last entry which is the 4 element range array (non-standard)
220
% PageSize with either dimension 0 will be detected in
221
% match_page_size, so we can allow it here
222
mark /PageSize [0 dup 16#7ffff dup] .dicttomark
228
mark 0 mark .dicttomark readonly .dicttomark
230
(%MediaDestination) 0
231
/Install {{.callinstall}} bind
232
/BeginPage {{.callbeginpage}} bind
233
/EndPage {{.callendpage}} bind
234
/Policies .defaultpolicies
235
/ImagingBBox //null % default value
236
/UseCIEColor /.getuseciecolor load
237
.dicttomark readonly def
239
% Define currentpagedevice so it creates the dictionary on demand if needed,
240
% adding all the required entries defined just above.
241
% We have to deal specially with entries that the driver may change
244
/.MediaSize dup % because it changes when PageSize is set
250
.dicttomark readonly def
251
/.makecurrentpagedevice { % - .makecurrentpagedevice <dict>
252
currentdevice //null .getdeviceparams
253
% Make the dictionary large enough to add defaulted entries.
254
counttomark 2 idiv .requiredattrs length add dict
255
counttomark 2 idiv { dup 4 2 roll put } repeat exch pop
256
% Add any missing required attributes.
257
% Make a writable and (if possible) local copy of any default
258
% dictionaries, to work around a bug in the output of WordPerfect,
259
% which assumes that these dictionaries are writable and local.
260
.currentglobal exch dup gcheck .setglobal
262
2 index 2 index known {
263
1 index /Policies eq {
264
% Merge policies from the device driver with defaults
265
2 index % <<>> /key value <<>>
266
3 2 roll get % <<>> value <<policies>>
268
2 index 2 index known {
279
exec 2 index 3 1 roll put
281
} forall exch .setglobal
287
pop .makecurrentpagedevice
289
% If any of the dynamic keys have changed,
290
% we must update the page device dictionary.
291
currentdevice //.dynamicppkeys .getdeviceparams .dicttomark {
292
% Stack: current key value
293
2 index 2 index .knownget { 1 index ne } { //true } ifelse
295
{ % This is the first entry being updated.
296
% Copy the dictionary to make it writable.
298
currentglobal 1 index dup gcheck currentglobal and setglobal
311
% If the device is the distiller device, update distillerparams that
312
% may have been changed by setdistillerparams
313
currentdevice .devicename /pdfwrite eq {
314
currentdistillerparams {
315
% Stack: current key value
316
2 index 2 index .knownget { 1 index ne } { //true } ifelse
317
{ 2 index 3 1 roll put } { pop pop } ifelse
320
% If the dictionary was global and is now local, copy
321
% any global subsidiary dictionaries to local VM. This
322
% too is to work around the Word Perfect bug (see above).
325
dup type /dicttype eq { dup gcheck } { //false } ifelse {
326
% Copy-on-write, see above.
328
3 -1 roll dup length dict .copydict
331
.copytree 2 index 3 1 roll put
337
% We would like to do a .setpagedevice so we don't keep
338
% re-creating the dictionary. Unfortunately, the effect
339
% of this is that if any dynamic key changes (PageCount
340
% in particular), we will do the equivalent of a
341
% setpagedevice at the next restore or grestore.
342
% Therefore, we make the dictionary read-only, but
343
% we don't store it away. I.e., NOT:
344
% dup wcheck { .setpagedevice .currentpagedevice pop } if
350
% Copy a dictionary recursively.
351
/.copytree { % <dict> .copytree <dict'>
352
dup length dict exch {
353
dup type /dicttype eq { .copytree } if 2 index 3 1 roll put
357
% The implementation of setpagedevice is quite complex. Currently,
358
% everything but the media matching algorithm is implemented here.
360
% By default, we only present the requested changes to the device,
361
% but there are some parameters that require special merging action.
362
% Define those parameters here, with the procedures that do the merging.
363
% The procedures are called as follows:
364
% <merged> <key> <new_value> -proc- <merged> <key> <new_value'>
370
{ 3 copy pop .knownget
372
{ pop dup length dict }
373
{ dup length 2 index length add dict .copydict }
378
ifelse .copydict readonly
382
/OutputAttributes 1 index
384
{ 3 copy pop .knownget
385
{ dup length 2 index length add dict .copydict }
389
.dicttomark readonly def
391
% M. Sweet, Easy Software Products:
393
% Define NOMEDIAATTRS to turn off the default (but unimplementable) media
394
% selection policies for setpagedevice. This is used by CUPS to support
395
% the standard Adobe media attributes.
397
% Define only PageSize for input attribute matching.
401
% Define no other keys used in media selection.
402
/.inputselectionkeys [
403
/noInputSelectionsKeys
406
% Define no keys used in output attribute matching.
411
% Define the keys used in input attribute matching.
413
/PageSize /MediaColor /MediaWeight /MediaType /InsertSheet /ManualFeed
414
% The following are documented in Adobe's supplement for v2017.
415
/LeadingEdge /MediaClass
417
% Define other keys used in media selection.
418
/.inputselectionkeys [
419
/MediaPosition /Orientation
422
% Define the keys used in output attribute matching.
428
% Define all the parameters that should always be copied to the merged
432
.mergespecial { pop } forall
433
.inputattrkeys aload pop
434
.inputselectionkeys aload pop
435
.outputattrkeys aload pop
438
% Define the parameters that should not be presented to the device.
439
% The procedures are called as follows:
440
% <merged> <key> <value> -proc-
441
% The procedure leaves all its operands on the stack and returns
442
% true iff the key/value pair should be presented to .putdeviceparams.
443
/.presentspecial mark
445
{ pop dup /LeadingEdge ne { //false } { pop } ifelse }
447
% We must ignore an explicit request for .MediaSize,
448
% because media matching always handles this.
451
/OutputDevice //false
452
/PageDeviceName //false
454
/PageSize //false % obsolete alias for .MediaSize
455
/InputAttributes //false
457
{ dup dup /PageSize eq exch /LeadingEdge eq or
459
{ { 2 index /InputAttributes .knownget { //null eq } { //true } ifelse } }
463
.inputselectionkeys { //false } forall
464
/OutputAttributes //false
466
{ { 2 index /OutputAttributes .knownget { //null eq } { //true } ifelse } }
474
{ % HACK: don't transmit the color map, because
475
% window systems can change the color map on their own
476
% incrementally. Someday we'll have a better
477
% solution for this....
480
/ViewerPreProcess //false
481
/ImagingBBox //false % This prevents the ImagingBBox value in the setpagedevice
482
% from affecting the device's ImagingBBox parameter, but
483
% does retain a 'shadow' copy at the PostScript level.
484
% This is done for Adobe compatibility since Adobe does
485
% render marks outside the ImagingBBox (and QuarkXpress
487
.dicttomark readonly def
489
% Define access to device defaults.
490
/.defaultdeviceparams
491
{ finddevice //null .getdeviceparams
494
% Select media (input or output). The hard work is done in an operator:
495
% <pagedict> <attrdict> <policydict> <keys> .matchmedia <key> true
496
% <pagedict> <attrdict> <policydict> <keys> .matchmedia false
497
% <pagedict> null <policydict> <keys> .matchmedia null true
498
/.selectmedia % <orig> <request> <merged> <failed> <-- retained
499
% <attrdict> <policydict> <attrkeys> <mediakey>
501
{ 5 index 5 -2 roll 4 index .matchmedia
502
% Stack: orig request merged failed attrkeys mediakey
504
{ 4 index 3 1 roll put pop
506
{ % Adobe's implementations have a "big hairy heuristic"
507
% to choose the set of keys to report as having failed the match.
508
% For the moment, we report any keys that are in the request
509
% and don't have the same value as in the original dictionary.
510
5 index 1 index .knownget
511
{ 4 index 3 1 roll put }
512
{ 3 index exch .undef }
514
{ % Stack: <orig> <request> <merged> <failed> <attrkey>
515
3 index 1 index .knownget
516
{ 5 index 2 index .knownget { ne } { pop //true } ifelse }
518
ifelse % Stack: ... <failed> <attrkey> <report>
519
{ 2 copy /rangecheck put }
527
% Apply Policies to any unprocessed failed requests.
528
% As we process each request entry, we replace the error name
529
% in the <failed> dictionary with the policy value,
530
% and we replace the key in the <merged> dictionary with its prior value
531
% (or remove it if it had no prior value).
533
% These procedures are called with the following on the stack:
534
% <orig> <merged> <failed> <Policies> <key> <policy>
535
% They are expected to consume the top 2 operands.
536
% NOTE: we currently treat all values other than 0, 1, or 7 (for PageSize)
537
% the same as 0, i.e., we signal an error.
539
% M. Sweet, Easy Software Products:
541
% Define NOMEDIAATTRS to turn off the default (but unimplementable) media
542
% selection policies for setpagedevice. This is used by CUPS to support
543
% the standard Adobe media attributes.
544
0 { % Set errorinfo and signal a configurationerror.
546
% NOMEDIAATTRS means that the default policy is 7...
547
pop 2 index exch 7 put
549
pop dup 4 index exch get 2 array astore
550
$error /errorinfo 3 -1 roll put
552
/setpagedevice .systemvar /configurationerror signalerror
555
1 { % Roll back the failed request to its previous status.
556
SETPDDEBUG { (Rolling back.) = pstack flush } if
557
3 index 2 index 3 -1 roll .forceput
558
4 index 1 index .knownget
559
{ 4 index 3 1 roll .forceput }
560
{ 3 index exch .undef }
563
7 { % For PageSize only, just impose the request.
565
{ pop pop 1 index /PageSize 7 put }
566
{ .policyprocs 0 get exec }
569
.dicttomark readonly def
570
/.applypolicies % <orig> <merged> <failed> .applypolicies
571
% <orig> <merged'> <failed'>
572
{ 1 index /Policies get 1 index
573
{ type /integertype eq
574
{ pop % already processed
576
{ 2 copy .knownget not { 1 index /PolicyNotFound get } if
577
% Stack: <orig> <merged> <failed> <Policies> <key>
579
.policyprocs 1 index .knownget not { .policyprocs 0 get } if exec
586
% Prepare to present parameters to the device, by spreading them onto the
587
% operand stack and removing any that shouldn't be presented.
588
/.prepareparams % <params> .prepareparams -mark- <key1> <value1> ...
590
{ % Stack: -mark- key1 value1 ... merged key value
591
.presentspecial 2 index .knownget
592
{ exec { 3 -1 roll } { pop pop } ifelse }
599
% Put device parameters without resetting currentpagedevice.
600
% (.putdeviceparams clears the current page device.)
601
/.putdeviceparamsonly % <device> <Policies|null> <require_all> -mark-
602
% <key1> <value1> ... .putdeviceparamsonly
603
% On success: <device> <eraseflag>
604
% On failure: <device> <Policies|null> <req_all> -mark-
605
% <key1> <error1> ...
607
{ counttomark 4 add 1 roll .putdeviceparams
608
dup type /booleantype eq { 3 } { counttomark 5 add } ifelse -1 roll
611
{ pop .putdeviceparams
616
% Try setting the device parameters from the merged request.
617
/.trysetparams % <merged> <(ignored)> <device> <Policies>
619
{ //true 4 index .prepareparams
620
% Add the computed .MediaSize.
621
% Stack: merged (ignored) device Policies -true-
622
% -mark- key1 value1 ...
623
counttomark 5 add index .computemediasize
624
exch pop exch pop /.MediaSize exch
625
SETPDDEBUG { (Putting.) = pstack flush } if
627
SETPDDEBUG { (Result of putting.) = pstack flush } if
630
% Compute the media size and initial matrix from a merged request (after
632
/.computemediasize % <request> .computemediasize
633
% <request> <matrix> <[width height]>
634
{ dup /PageSize get % requested page size
635
1 index /InputAttributes get
636
2 index (%MediaSource) get get /PageSize get % media size
638
2 index /Policies get
639
dup /PageSize .knownget
640
{ exch pop } { /PolicyNotFound get } ifelse % PageSize policy,
642
3 index /Orientation .knownget not { //null } if
643
4 index /RollFedMedia .knownget not { //false } if
644
matrix .matchpagesize not {
645
% This is a "can't happen" condition!
646
/setpagedevice .systemvar /rangecheck signalerror
651
% ---------------- setpagedevice itself ---------------- %
654
{ % We mustn't pop the argument until the very end,
655
% so that the pseudo-operator machinery can restore the stack
656
% if an error occurs.
657
mark 1 index currentpagedevice
659
% Check whether we are changing OutputDevice;
660
% also handle the case where the current device
661
% is not a page device.
662
% Stack: mark <request> <current>
663
SETPDDEBUG { (Checking.) = pstack flush } if
665
dup /OutputDevice .knownget
666
{ % Current device is a page device.
667
2 index /OutputDevice .knownget
668
{ % A specific OutputDevice was requested.
678
{ % Current device is not a page device.
679
% Use the default device.
680
1 index /OutputDevice .knownget not { .defaultdevicename } if
686
{ exch pop .defaultdeviceparams
687
% In case of duplicate keys, .dicttomark takes the entry
688
% lower on the stack, so we can just append the defaults here.
689
.requiredattrs { exec } forall .dicttomark
693
% Check whether a viewer wants to intervene.
694
% We must check both the request (which takes precedence)
695
% and the current dictionary.
696
% Stack: mark <request> <orig>
697
exch dup /ViewerPreProcess .knownget
699
{ 1 index /ViewerPreProcess .knownget { exec } if }
702
% Construct a merged request from the actual request plus
703
% any keys that should always be propagated.
704
% Stack: mark <request> <orig>
705
SETPDDEBUG { (Merging.) = pstack flush } if
707
exch 1 index length 1 index length add dict
709
{ % Stack: <orig> <request> <merged> <key>
710
3 index 1 index .knownget { 3 copy put pop } if pop
713
% Stack: <orig> <request> <merged>
715
{ % stack: <orig> <request> <merged> <merged> <rkey> <rvalue>
716
.mergespecial 2 index .knownget { exec } if
720
% Hack: if FIXEDRESOLUTION is true, discard any attempt to
721
% change HWResolution.
722
FIXEDRESOLUTION { dup /HWResolution .undef } if
723
% Hack: if FIXEDMEDIA is true, discard any attempt to change
724
% PageSize or HWSize.
726
{ dup /PageSize 4 index /PageSize get put
727
dup /HWSize 4 index /HWSize get put
729
% Hack: to work around some files that take a PageSize
730
% from InputAttributes and impose it, discard any attempt
731
% to set PageSize to a 4-element value.
732
% Stack: mark <orig> <request> <merged>
733
dup /PageSize .knownget {
735
dup /PageSize 4 index /PageSize get put
739
% Select input and output media.
740
% Stack: mark <orig> <request> <merged>
741
SETPDDEBUG { (Selecting.) = pstack flush } if
744
1 index /InputAttributes .knownget
745
{ 2 index /Policies get
746
.inputattrkeys (%MediaSource) cvn .selectmedia
748
1 index /OutputAttributes .knownget
749
{ 2 index /Policies get
750
.outputattrkeys (%MediaDestination) cvn .selectmedia
752
3 -1 roll 4 1 roll % temporarily swap orig & request
754
3 -1 roll 4 1 roll % swap back
756
% Construct the new device, and attempt to set its attributes.
757
% Stack: mark <orig> <request> <merged> <failed>
758
SETPDDEBUG { (Constructing.) = pstack flush } if
760
currentdevice .devicename 2 index /OutputDevice get eq
762
{ 1 index /OutputDevice get finddevice }
764
%**************** We should copy the device here,
765
%**************** but since we can't close the old device,
766
%**************** we don't. This is WRONG.
767
%****************copydevice
768
2 index /Policies get
770
dup type /booleantype ne
771
{ % The request failed.
772
% Stack: ... <orig> <request> <merged> <failed> <device>
773
% <Policies> true mark <name> <errorname> ...
774
SETPDDEBUG { (Recovering.) = pstack flush } if
775
counttomark 4 add index
776
counttomark 2 idiv { dup 4 -2 roll put } repeat
778
% Stack: mark ... <orig> <request> <merged> <failed> <device>
780
6 2 roll 3 -1 roll 4 1 roll
782
3 -1 roll 4 1 roll 6 -2 roll
783
.trysetparams % shouldn't fail!
784
dup type /booleantype ne
785
{ 2 { counttomark 1 add 1 roll cleartomark } repeat
786
/setpagedevice .systemvar exch signalerror
792
% The attempt succeeded. Install the new device.
793
% Stack: mark ... <merged> <failed> <device> <eraseflag>
794
SETPDDEBUG { (Installing.) = pstack flush } if
797
{ 1 //true .outputpage
798
(>>setpagedevice, press <return> to continue<<\n) .confirm
801
% .setdevice clears the current page device!
802
.currentpagedevice pop exch
806
% Implement UseCIEColor directly if this is a LL3 system.
807
% The color substitution feature is now implemented in
808
% the interpreter, and this is used as an optimization.
810
% NB: This shoud be the only use of the .setuseciecolor
813
% If UseCIEColor is transitioned to false, set some
814
% color space other than /DeviceGray, to insure that
815
% initgraphics will actually perform a setcolorspace
816
% operation (there is an optimization in setcolorspace
817
% that does nothing if the operand and current color
818
% spaces are the same, and UseCIEColor is false).
820
/.setuseciecolor where
822
pop 1 index /UseCIEColor .knownget
824
dup .setuseciecolor not
825
{ /DeviceRGB setcolorspace }
832
% Merge the request into the current page device,
833
% unless we're changing the OutputDevice.
834
% Stack: mark ... <merged> <failed>
835
exch currentpagedevice dup length 2 index length add dict
836
% Stack: mark ... <failed> <merged> <current> <newdict>
837
2 index /OutputDevice .knownget {
838
2 index /OutputDevice .knownget not { //null } if eq
842
% Same OutputDevice, merge the dictionaries.
845
% Different OutputDevice, discard the old dictionary.
848
% Initialize the default matrix, taking media matching
850
.computemediasize pop initmatrix concat
851
dup /PageOffset .knownget
852
{ % Translate by the given number of 1/72" units in device X/Y.
854
2 index /HWResolution get dup 1 get exch 0 get
855
4 -1 roll mul 72 div 3 1 roll mul 72 div
856
idtransform translate
859
% We must install the new page device dictionary
860
% before calling the Install procedure.
862
.setdefaulthalftone % Set the default screen before calling Install.
863
dup /Install .knownget {
864
{ .execinstall } stopped {
865
pop % Install procedure failed. One element will have been left on the stack.
866
% stack: mark <orig> <request> <failed> <merged>
867
1 index /Install $error /errorname get put % Put it in the "failed" dict
868
% .applypolicies needs stack: <orig> <merged> <failed>
869
exch 4 2 roll exch 4 2 roll .applypolicies exch 4 2 roll exch 4 2 roll
870
% Now execute the old Install -- failures after this are not handled
871
dup /Install .knownget { { .execinstall } stopped { pop } if } if
881
% We break out the code after calling the Install procedure into a
882
% separate procedure, since it is executed even if Install causes an error.
883
% By making .execinstall a separate operator procedure, we get the stacks
884
% mostly restored if it fails, except for one element (the operand).
885
% Thus if it fails, there will be one element left on the op stack.
887
/.execinstall { % <proc> .execinstall -
888
dup % element left on the stack if the exec fails.
890
% Because the interpreter optimizes tail calls, we can't just let
891
% the body of this procedure be 'exec', because that would lose
892
% the stack protection that is the whole reason for having the
893
% procedure in the first place. The 'pop' for the dummy element
894
% on the op stack suffices.
899
/.postinstall { % mark ... <failed> <merged> .postinstall -
900
matrix currentmatrix .setdefaultmatrix
901
% Erase and initialize the page.
903
currentoverprint //false setoverprint 1 setcolor
905
0 setcolor setoverprint
908
% Clean up, calling PolicyReport if needed.
909
% Stack: mark ... <failed> <merged>
910
SETPDDEBUG { (Finishing.) = pstack flush } if
913
{ 1 index /Policies get /PolicyReport get
914
counttomark 1 add 2 roll cleartomark