REM > Support - for PostScript printers

/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Printers+ front-end.
 *
 * The Initial Developer of the Printers front-end is Acorn Computers Ltd.
 * The Initial Developer of the Printers+ extensions is RISCOS Ltd.
 *
 * Portions created by the Initial Developers are Copyright (C) 2003
 * the Initial Developers. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */

/* Changes list:
 *
 * RJW: Created from SupportPS
 * 
 */

#include "Values.h"
#include "Trace.h"

DEF FNpdf_support(buff%)
  LOCAL reason%,psup%,prnt%,prdt%,cnfg%,xbuff%,psize_head%,code_entry%
  REM On entry, A%=interface pointer. This must be preserved.
  reason%=buff%!0
  psup%=buff%!4
  prnt%=buff%!8
  xbuff%=buff%!12
  psize_head%=buff%!16
  code_entry%=buff%!20
  IF prnt% THEN
    prdt%=FNprinter_find_prdata_entry(psup%,$prnt%!CONST_prnt_type)
    cnfg%=prnt%!CONST_prnt_cnfg
  ENDIF
  CASE reason% OF
  WHEN -1: PROCpdf_m1
  WHEN -3: PROCpdf_m3
  WHEN -4: PROCpdf_m4
  WHEN -5: PROCpdf_m5
  WHEN -6: PROCpdf_m6
  WHEN -7: PROCpdf_m7
  WHEN -8: PROCpdf_m8
  WHEN -9: PROCpdf_m9
  WHEN-10: PROCpdf_m10
  WHEN 3: PROCpdf_p3
  WHEN 6: PROCpdf_p6
  WHEN 8: PROCpdf_p8
  WHEN 9: PROCpdf_p9
  WHEN 17,18: PROCpdf_p17
  ENDCASE
=FALSE

DEF PROCpdf_m1
  REM VDU: PROCftracef("PROCpdf_m1")
  REM VDU: psup%!CONST_psup_flags=psup%!CONST_psup_flags OR 200<<8 OR %11000
  psup%!CONST_psup_flags = psup%!CONST_psup_flags OR (1<<5):REM need to be able to write
  psup%!CONST_psup_type=&FF5
  psup%!CONST_psup_text=%1011
  psup%!CONST_psup_cnfg=CONST_cnfg_pdf_MAX/4
  psup%!CONST_psup_vsn=1
  REM note that the version number really only reflects
  REM the status of the files being read, ie only change
  REM this number if the file contents change.
  psup%!CONST_psup_dvsn=100
  buff%!0 =&80151
  buff%!4 =&80150
  buff%!8 =&8014F
  buff%!12=&8014E
  buff%!16=&8014D
  buff%!20=&8014C
  buff%!24=0
  SYS"Wimp_AddMessages",buff%
  IFFNrmload_latest_module("PDriver","Printers:Modules.PDriver")
  IFFNrmload_latest_module("PDriverPDF","Printers:Modules.PDriverPDF")
  IFFNrmload_latest_module("PDFDriver","Printers:Modules.PDFDriver")
  IFFNrmload_latest_module("MakePSFont","Printers:Modules.MakePSFont")
ENDPROC

DEF PROCpdf_m3
  REM initialise the configuration window
  LOCAL config%,pdf_i%
  REM VDU: PROCftracef("PROCpdf_m3")
  config%=FNprinter_find_window(prnt%,"configure")
  PROCicon_write(config%,13,FNprinter_read_string(prnt%!CONST_prnt_name))
  PROCicon_write(config%,6,$prnt%!CONST_prnt_type)
  pdf_i%=!cnfg%!CONST_cnfg_pdf_flags
  IF pdf_i% AND 1 PROCicon_select(config%,8)ELSE PROCicon_deselect(config%,8)
  IF pdf_i% AND 2 PROCicon_select(config%,11)ELSE PROCicon_deselect(config%,11)
  PROCicon_write(config%,18,FNmsg_0(psup%!CONST_psup_msg,"PO"+STR$((pdf_i% AND 4)>>2)))
  IF FNhas_external_config_app(prnt%) THEN
    PROCicon_unshade(config%,39)
  ELSE
    PROCicon_shade(config%,39)
  ENDIF
  IF FNprinter_read_string_entry(prdt%,CONST_pdf_template_feeds)="" THEN
    REM no feed information - choose between manual or automatic
    PROCicon_write(config%,3,FNmsg_0(psup%!CONST_psup_msg,"PF"+STR$((pdf_i% AND 8)>>3)))
  ELSE
    IF cnfg%!CONST_cnfg_pdf_feed = 0 THEN
      REM using default settings in printer
      PROCicon_write(config%,3,FNmsg_0(psup%!CONST_psup_msg,"ME1b"))
    ELSE
      PROCicon_write(config%,3,FNpdf_get_feed_name(FNprinter_read_string(cnfg%!CONST_cnfg_pdf_feed)))
    ENDIF
  ENDIF
  IF FNprinter_read_integer_entry(prdt%,CONST_pdf_template_colour)=1 THEN
    PROCicon_unshade(config%,7)
    IF pdf_i% AND 16 PROCicon_select(config%,7)ELSE PROCicon_deselect(config%,7)
  ELSE
    PROCicon_deselect(config%,7)
    PROCicon_shade(config%,7)
  ENDIF
  IF pdf_i% AND 32 PROCicon_select(config%,31)ELSE PROCicon_deselect(config%,31)
  IF pdf_i% AND 64 PROCicon_select(config%,32)ELSE PROCicon_deselect(config%,32)
  PROCicon_write(config%,30,STR$((pdf_i% AND &FF00)>>8))
  PROCicon_write(config%,16,FNmsg_0(psup%!CONST_psup_msg,"TC"+STR$((pdf_i% AND &FF0000)>>16)))
  PROCicon_write(config%,23,FNmsg_0(psup%!CONST_psup_msg,"CC"+STR$((pdf_i% AND &FF000000)>>24)))
  pdf_i%=prnt%!CONST_prnt_psze
  PROCicon_write(config%,27,$pdf_i%!CONST_psze_name)
ENDPROC

DEF PROCpdf_m4
  REM create a CNFG block with suitable defaults
  LOCAL pdf_s$,pdf_i%,pdf_t%,B%,C%,pdf_n$
  REM VDU: PROCftracef("PROCpdf_m4")

  cnfg%!CONST_cnfg_pdf_flags=FNstore_integer(100<<8)
  $buff%=FNprinter_read_string_entry(prdt%,CONST_pdf_template_shnme): B%=buff%: C%=2: prnt%!CONST_prnt_name=USR(code_entry%+CONST_entry_store_string)
  pdf_s$=FNprinter_read_string_entry(prdt%,CONST_pdf_template_spnme)
  IF pdf_s$<>"ps" $buff%=pdf_s$: B%=buff%: C%=2: prnt%!CONST_prnt_sprt=USR(code_entry%+CONST_entry_store_string)
  REM initialise the best paper size we can find ...
  pdf_i%=psize_head%
  pdf_s$=FNmsg_0(psup%!CONST_psup_msg,"PAP")
  WHILE pdf_s$<>FNprinter_read_string(pdf_i%!CONST_psze_name)
   pdf_i%=pdf_i%!CONST_psze_next
   IF pdf_i%=0 pdf_i%=psize_head%: pdf_s$=FNprinter_read_string(pdf_i%!CONST_psze_name)
  ENDWHILE
  prnt%!CONST_prnt_psze=pdf_i%
  pdf_i%=0
  PROCpdf_ensure_dir
  REPEAT
   SYS"OS_File",5,"PrinterChoices:pdf.Printers."+STR$ pdf_i% TO pdf_t%
   IF pdf_t% pdf_i%+=1
  UNTIL pdf_t%=0
  cnfg%!CONST_cnfg_pdf_fonts=FNstore_integer(pdf_i%)
  PROCpdf_create_default_font_file
  PROCpdf_ensure_fonts(prnt%,FALSE)

  REM if this printer supports fast parallel, set the appropriate flag
  pdf_i%=FNprinter_read_integer_entry(prdt%,CONST_pdf_template_fastparl)
  IFpdf_i%<>0 prnt%!CONST_prnt_flags = prnt%!CONST_prnt_flags OR (1<<7)
  
  prnt%!CONST_prnt_flags = prnt%!CONST_prnt_flags OR CONST_prnt_flags_notext

  REM if we have some paper feeds, pick the first file as the default, otherwise
  REM we will assume automatic paper feed.
  pdf_s$=FNprinter_read_string_entry(prdt%,CONST_pdf_template_feeds)
  IFpdf_s$="" THEN
    cnfg%!CONST_cnfg_pdf_feed = 0
  ELSE
    SYS"OS_GBPB",9,pdf_s$,buff%,1,0,256,"*" TO ,,,pdf_i%
    IFpdf_i%=1 THEN
      CALL Z%,buff%,pdf_n$
      $buff%=pdf_s$+"."+pdf_n$
      IFFNpdf_get_feed_name($buff%)<>"" THEN
        B%=buff%:C%=2:cnfg%!CONST_cnfg_pdf_feed=USR(code_entry%+CONST_entry_store_string)
      ELSE
        cnfg%!CONST_cnfg_pdf_feed = 0
      ENDIF
    ENDIF
  ENDIF
ENDPROC

DEF PROCpdf_m5
  REM check to see if there are any unused font files
  LOCAL pdf_i%,pdf_j%
  REM VDU: PROCftracef("PROCpdf_m5")
  PROCpdf_ensure_dir
  REPEAT
   SYS"OS_GBPB",9,"PrinterChoices:pdf.Printers"+CHR$0,buff%,1,pdf_i%,128,"*" TO ,,,pdf_j%,pdf_i%
   IF pdf_j%=1 THEN
    pdf_j%=buff%: WHILE ?pdf_j%: pdf_j%+=1: ENDWHILE: ?pdf_j%=13
    pdf_j%=prnt%
    WHILE pdf_j%>0
     IF pdf_j%!CONST_prnt_psup=psup% THEN
      REM got a printer in our class - does the name of the font file match?
      cnfg%=pdf_j%!CONST_prnt_cnfg
      IF $buff%=STR$ !cnfg%!CONST_cnfg_pdf_fonts THEN
       REM yes - leave it alone
       pdf_j%=-1
      ELSE
       REM no - try the next printer
       pdf_j%=pdf_j%!CONST_prnt_next
      ENDIF
     ELSE
      REM not our class - try the next printer
      pdf_j%=pdf_j%!CONST_prnt_next
     ENDIF
    ENDWHILE
    IF pdf_j%=0 THEN
     REM failed to match - delete the file
     REM VDU: PROCftracef("PROCpdf_m5: deleting PrinterChoices:pdf.Printers."+$buff%)
     SYS"OS_File",6,"PrinterChoices:pdf.Printers."+$buff%
     REM VDU: PROCftracef("PROCpdf_m5: deleted")
     REM need to reset the offset now
     pdf_i%=0
    ENDIF
   ENDIF
  UNTIL pdf_i%=-1
  REM now see if there are any printers that need fonts downloading
  PROCpdf_find_fonts_to_do(prnt%)
  REM VDU: PROCftracef("PROCpdf_m5 done")
ENDPROC

DEF PROCpdf_m6
  REM do whatever is necessary to prime the specified printer
  REM 0 is the magic number for the PostScript driver
  LOCAL pdf_i%,pdf_s$,pdf_f$,pdf_t$,cnct%,ptr%,pdf_extra$
  LOCAL pxres%,pyres%,pxres_halftone%,pyres_halftone%,colour%,pslevel%
  LOCAL local_margin%,local_pl%,local_pr%,local_pb%,local_pt%
  LOCAL local_psze%,local_pw%,local_ph%,local_fsize%,local_w%
  LOCAL local_h%,local_A%,local_B%,local_G%
  REM VDU: PROCftracef("PROCpdf_m6")
  SYS"PDriver_SelectDriver",8
  pdf_s$=FNprinter_read_string(prnt%!CONST_prnt_name)
  IF pdf_s$="" THEN
   pdf_s$=$prnt%!CONST_prnt_type
   IF LEN pdf_s$>20 THEN
    pdf_i%=LEN pdf_s$
    WHILE MID$(pdf_s$,pdf_i%,1)<>" " AND pdf_i%>0
     pdf_i%-=1
    ENDWHILE
    IF pdf_i% THEN
     pdf_s$=LEFT$(pdf_s$,pdf_i%-1)
    ELSE
     pdf_s$=LEFT$(pdf_s$,20)
    ENDIF
   ENDIF
  ENDIF
  pxres%=FNprinter_read_integer_entry(prdt%,CONST_pdf_template_pxres)
  pyres%=FNprinter_read_integer_entry(prdt%,CONST_pdf_template_pyres)
  pxres_halftone%=FNprinter_read_integer_entry(prdt%,CONST_pdf_template_pxhalf)
  pyres_halftone%=FNprinter_read_integer_entry(prdt%,CONST_pdf_template_pyhalf)
  pslevel%=FNprinter_read_integer_entry(prdt%,CONST_pdf_template_pslevel)
  IF pslevel%<1 OR pslevel%>32 THEN pslevel%=1
  IF !cnfg%!CONST_cnfg_pdf_flags AND 16 colour%=&2000001 ELSE colour%=&2000000
  SYS"XPDriver_SetInfo",,pxres%,pyres%,colour%,pdf_s$,pxres_halftone%,pyres_halftone%,0 TO ptr%;pdf_i%
  IF pdf_i% AND 1 THEN
   pdf_s$="": ptr%+=4
   WHILE ?ptr%: pdf_s$+=CHR$ ?ptr%: ptr%+=1: ENDWHILE
   ERROR CONST_error_ok,pdf_s$
   ENDPROC
  ENDIF
  cnct%=prnt%!CONST_prnt_cnct
  CASE cnct%!CONST_cnct_type OF
  WHEN 1,2: pdf_i%=1: REM enable control D output
  OTHERWISE: pdf_i%=0: REM disable control D output
  ENDCASE
  IF !cnfg%!CONST_cnfg_pdf_flags AND 32 pdf_i%+=2: REM verbose prologue
  IF !cnfg%!CONST_cnfg_pdf_flags AND 64 pdf_i%+=4: REM accented chars
  pdf_i%+=(pslevel%-1)*8: REM PostScript level, in bits 3-7
  SYS"PDriver_SetDriver",pdf_i%
  SYS"OS_CLI","Set PDriver$PSprologue Printers:ps.PSfiles.PSprolog"
  SYS"OS_CLI","Set PDriver$PSprologue2 Printers:ps.PSfiles.Level"+ \
    STR$(pslevel%)+"."+FNprinter_read_string_entry(prdt%,CONST_pdf_template_prologue2)
  local_psze%=prnt%!CONST_prnt_psze
  REM VDU: PROCftracef("Ptr to paper size block = &"+STR$~(local_psze%))
  pdf_s$=$local_psze%!CONST_psze_name
  REM VDU: PROCftracef("Paper size name = "+pdf_s$)
  pdf_i%=0
  WHILE MID$(pdf_s$,pdf_i%,1)<>" " AND pdf_i%<=LEN pdf_s$
    pdf_i%+=1
  ENDWHILE
  pdf_s$=LEFT$(pdf_s$,pdf_i%-1)

  pdf_extra$=""
  SYS"OS_CLI","Unset PDriver$PSextra"
  SYS"OS_CLI","Unset PDriver$PSpaper"
  SYS"OS_CLI","Unset PDriver$PSfeed"

  SYS"OS_File",17,"Printers:pdf.Paper."+FNtask_lower(pdf_s$) TO pdf_i%
  IFpdf_i%<>1 THEN
    /* paper file can't be found - resort to original kludge */
    pdf_extra$=FNmsg_2(psup%!CONST_psup_msg,"PT",pdf_s$,FNtask_lower(pdf_s$))
  ELSE
    /* set the system variable PDriver$PSPaper to be the file name associated with the specified paper */
    SYS"OS_CLI","Set PDriver$PSPaper Printers:pdf.Paper."+FNtask_lower(pdf_s$)
  ENDIF

  IF cnfg%!CONST_cnfg_pdf_feed <> 0 THEN
    /* set the system variable PDriver$PSFeed to be the file name associated with the specified feed */
    SYS"OS_CLI","Set PDriver$PSFeed "+FNprinter_read_string(cnfg%!CONST_cnfg_pdf_feed)
  ELSE
    REM only do auto/manual code if we do not have any feed information otherwise this
    REM means that the user wants to use the default printer setting
    IF FNprinter_read_string_entry(prdt%,CONST_pdf_template_feeds)="" THEN
      IF !cnfg%!CONST_cnfg_pdf_flags AND 8 THEN
       pdf_f$=FNungstrans(FNprinter_read_boolean_string_entry(prdt%,CONST_pdf_template_manualfeed,TRUE))
      ELSE
       pdf_f$=FNungstrans(FNprinter_read_boolean_string_entry(prdt%,CONST_pdf_template_manualfeed,FALSE))
      ENDIF
      IF pdf_extra$<>"" pdf_extra$=pdf_f$+"|J"+pdf_extra$ ELSE pdf_extra$=pdf_f$
    ENDIF
  ENDIF

  IF pdf_extra$<>"" SYS"OS_CLI","Set PDriver$PSextra "+pdf_extra$

  SYS"OS_CLI","Unset PDriver$TextChars1": REM no character translation to speak of
  local_margin%=50
  local_pl% = local_psze%!CONST_psze_lmargin DIV 100 + 1 + local_margin%
  local_pr% = local_psze%!CONST_psze_rmargin DIV 100 - local_margin%
  local_pb% = local_psze%!CONST_psze_bmargin DIV 100 + 1 + local_margin%
  local_pt% = local_psze%!CONST_psze_tmargin DIV 100 - local_margin%
  IF(!cnfg%!CONST_cnfg_pdf_flags AND 4)=0 THEN
   IF !cnfg%!CONST_cnfg_pdf_flags AND 1 local_pt%-=150
   local_pw% = local_pr%-local_pl%
   local_ph% = local_pt%-local_pb%
  ELSE
   IF !cnfg%!CONST_cnfg_pdf_flags AND 1 local_pl%+=150
   local_pw% = local_pt%-local_pb%
   local_ph% = local_pr%-local_pl%
  ENDIF

  local_fsize%=(!cnfg%!CONST_cnfg_pdf_flags AND &FF00)>>8
  REM VDU: PROCftracef("Local font size is "+STR$ local_fsize%)
  local_w%=0.72*local_fsize%
  local_h%=1.2*local_fsize%
  REM VDU: PROCftracef("=> (w, h) = ("+STR$ local_w%+", "+STR$ local_h%+")")
  local_pw%=local_pw% DIV local_w%
  local_ph%=local_ph% DIV local_h%
  IF !cnfg%!CONST_cnfg_pdf_flags AND 1 THEN
   local_G%=2
   local_A%=local_ph%+2
  ELSE
   local_G%=0
   local_A%=local_ph%
  ENDIF
  local_B%=(local_pw%+2)DIV(1+((!cnfg%!CONST_cnfg_pdf_flags AND &FF0000)>>16))-2
  pdf_t$="-Ph "+STR$ local_A%+" -Pw "+STR$ local_B%+" -Mt "+STR$ local_psze%!CONST_psze_ttop
  pdf_t$+=" -Mb "+STR$ local_psze%!CONST_psze_tbottom+" -Ml "+STR$ local_psze%!CONST_psze_tleft
  pdf_t$+=" -Mr "+STR$ local_psze%!CONST_psze_tright+" -Th "+STR$ local_G%
  SYS"OS_CLI","Set PDriver$TextPage "+pdf_t$
  PROCpdf_add_fonts(FALSE)
  REM VDU: PROCftracef("PROCpdf_m6 done")
ENDPROC

DEF PROCpdf_m7
  LOCAL queu%,pdf_p%,pdf_i%,B%,C%
  REM VDU: PROCftracef("PROCpdf_m7")
  queu%=!xbuff%
/*  REM we're all done now - free the private block */
  pdf_p%=queu%!CONST_queu_tprv
  IF pdf_p% THEN
   REM free the two strings we hold
   PROCfree_structure(pdf_p%!CONST_tprv_pdf_bbox)
   PROCfree_structure(pdf_p%!CONST_tprv_pdf_transform)
   B%=CONST_ident_TPRV: C%=pdf_p%: CALL code_entry%+CONST_entry_heap_free
   queu%!CONST_queu_tprv=0
  ENDIF
  REM now free the character translation list
  pdf_p%=queu%!CONST_queu_char
  WHILE pdf_p%
   pdf_i%=!pdf_p%
   B%=CONST_ident_CHAR: C%=pdf_p%: CALL code_entry%+CONST_entry_heap_free
   pdf_p%=pdf_i%
  ENDWHILE
  queu%!CONST_queu_char=0
ENDPROC

DEF PROCpdf_m9
  REM printer being removed
  REM delete the printer font file
  SYS"XOS_File",6,"PrinterChoices:pdf.Printers."+STR$(!cnfg%!CONST_cnfg_pdf_fonts)
  REM then check the download window
  PROCpdf_m10
ENDPROC

DEF PROCpdf_m10
  REM printer being deactivated
  REM if the font download window is open for this printer, move on
  REM to the next one
  LOCAL pdf_i%
  REM VDU: PROCftracef("PROCpdf_m9")
  pdf_i%=psup%!CONST_psup_wind
  WHILE pdf_i%
   IF $(pdf_i%+CONST_wind_name)="download" THEN
    REM is the window open?
    !buff%=pdf_i%!CONST_wind_hand: SYS"Wimp_GetWindowState",,buff%
    IF buff%!32 AND 1<<16 THEN
     REM yes - it is for this printer? If so, move to next printer
     IF pdf_i%!CONST_wind_prnt=prnt% THEN
      SYS"Wimp_CloseWindow",,buff%
      PROCpdf_find_fonts_to_do(prnt%!CONST_prnt_next)
     ENDIF
    ENDIF
    pdf_i%=0
   ELSE
    pdf_i%=pdf_i%!CONST_wind_next
   ENDIF
  ENDWHILE
ENDPROC

DEF PROCpdf_p3
  REM a window closing
  LOCAL pdf_i%
  REM VDU: PROCftracef("PROCpdf_p3")
  SYS"Wimp_CloseWindow",,xbuff%
  pdf_i%=psup%!CONST_psup_wind
  WHILE pdf_i%
    IF pdf_i%!CONST_wind_hand=!xbuff% THEN
      IF $(pdf_i%+CONST_wind_name)="download" THEN
        REM if currently selected printer - reselect it so the mappings are good
        IF prnt%!CONST_prnt_flags AND 2 !buff%=20: buff%!12=0: buff%!16=&80152: SYS"Wimp_SendMessage",17,buff%,0
        REM since the user has decided not to download the fonts, cancel the flag bit
        pdf_i%=prnt%!CONST_prnt_fonts
        WHILE pdf_i%
          pdf_i%!CONST_fonts_flags=pdf_i%!CONST_fonts_flags AND NOT(1<<31)
          pdf_i%=pdf_i%!CONST_fonts_next
        ENDWHILE
        PROCpdf_find_fonts_to_do(prnt%!CONST_prnt_next)
      ENDIF
      pdf_i%=0
    ELSE
      pdf_i%=pdf_i%!CONST_wind_next
    ENDIF
  ENDWHILE
ENDPROC

DEF PROCpdf_p6
  REM mouseclick on the configure window
  LOCAL wind%,dummy%
  REM VDU: PROCftracef("PROCpdf_p6")
  CASE xbuff%!8 OF
    WHEN 2: REM Menu
      CASE xbuff%!16 OF
        WHEN  4: PROCpdf_menu("ME1",TRUE,TRUE)
        WHEN 20: PROCpdf_menu("ME2",TRUE,TRUE)
        WHEN 19: PROCpdf_menu("ME3",TRUE,TRUE)
        WHEN 24: PROCpdf_menu("ME4",TRUE,TRUE)
        WHEN 26: PROCpdf_menu("MP1",TRUE,TRUE)
      ENDCASE
    WHEN 4: REM Select
      CASE xbuff%!16 OF
        WHEN 25
          REM VDU: PROCftracef("saving and closing configuration (click SELECT)")
          wind%=xbuff%!12
          PROCpdf_save_configuration(wind%)
          !xbuff%=wind%
          SYS"Wimp_CloseWindow",,xbuff%
        WHEN  4: PROCpdf_menu("ME1",TRUE,TRUE)
        WHEN 20: PROCpdf_menu("ME2",TRUE,TRUE)
        WHEN 19: PROCpdf_menu("ME3",TRUE,TRUE)
        WHEN 24: PROCpdf_menu("ME4",TRUE,TRUE)
        WHEN 26: PROCpdf_menu("MP1",TRUE,TRUE)
        WHEN 33
          !xbuff%=xbuff%!12
          SYS"Wimp_CloseWindow",,xbuff%
        WHEN 39
          dummy%=FNexternal_config_app(prnt%)
      ENDCASE
    WHEN 1: REM Adjust
      CASE xbuff%!16 OF
        WHEN 25
          wind%=xbuff%!12
          PROCpdf_save_configuration(wind%)
        WHEN 39
          dummy%=FNexternal_config_app(prnt%)
      ENDCASE
  ENDCASE
ENDPROC

DEF PROCpdf_p8
  REM a key press!
  LOCAL pdf_i%
  REM VDU: PROCftracef("PROCpdf_p8")
  pdf_i%=psup%!CONST_psup_wind
  WHILE pdf_i%
    IF pdf_i%!CONST_wind_hand=!xbuff% THEN
      IF xbuff%!24=13 THEN
        CASE $(pdf_i%+CONST_wind_name)OF
          WHEN "configure"
            REM VDU: PROCftracef("saving and closing configuration (press RETURN)")
            SYS "Wimp_CloseWindow",,xbuff%
            PROCpdf_save_configuration(!xbuff%)
          WHEN "download"
            SYS "Wimp_CloseWindow",,xbuff%
            PROCpdf_download_fonts(!xbuff%)
        ENDCASE
      ELSE
        SYS "Wimp_ProcessKey",xbuff%!24
      ENDIF

      ENDPROC
    ENDIF

    pdf_i%=pdf_i%!CONST_wind_next
  ENDWHILE
ENDPROC

DEF PROCpdf_p9
  LOCAL adjust%,wind%,icon%,ptr%
/*
 * REM menu selections are easy ... we just write the
 * REM selected string into the appropriate icon.
 * REM some other actions may be taken to ensure that
 * REM other choices are OK, but we don't touch any
 * REM data yet.
 */
  REM VDU: PROCftracef("PROCpdf_p9")
  wind%=FNprinter_find_window(prnt%,"configure")
  adjust%=FNwas_adjust_used
  CASE pdf_menu_chsn$ OF
  WHEN "ME1": icon%=3
  WHEN "ME2": icon%=16
  WHEN "ME3": icon%=18
  WHEN "ME4": icon%=23
  WHEN "MP1": icon%=27
  ENDCASE
  ptr%=pdf_menu%+28+!xbuff%*24
  IF ptr%!8 AND &100 THEN
   PROCicon_write(wind%,icon%,$ptr%!12)
  ELSE
   PROCicon_write(wind%,icon%,$(ptr%+12))
  ENDIF
  IF pdf_menu_chsn$="ME3" THEN
   IF FNicon_read(wind%,18)=FNmsg_0(psup%!CONST_psup_msg,"PO0")THEN
    PROCicon_write(wind%,16,FNmsg_0(psup%!CONST_psup_msg,"PC"))
    PROCicon_write(wind%,30,FNmsg_0(psup%!CONST_psup_msg,"PS"))
   ELSE
    PROCicon_write(wind%,16,FNmsg_0(psup%!CONST_psup_msg,"LC"))
    PROCicon_write(wind%,30,FNmsg_0(psup%!CONST_psup_msg,"LS"))
   ENDIF
  ENDIF
  IF adjust% THEN
   SYS"Wimp_GetPointerInfo",,xbuff%
   PROCpdf_menu(pdf_menu_chsn$,FALSE,FALSE)
  ENDIF
ENDPROC

DEF PROCpdf_p17
  LOCAL wind%,pdf_s$,pdf_t$,pdf_f$,size%,dest%,recv%
  REM VDU: PROCftracef("PROCpdf_p17")
  CASE xbuff%!16 OF
  WHEN &502:
    wind%=psup%!CONST_psup_wind
    WHILE wind%
      IF wind%!CONST_wind_hand=xbuff%!32 THEN
        CASE $(wind%+CONST_wind_name)OF
          WHEN "configure": pdf_s$=STR$ xbuff%!36
            CASE xbuff%!36 OF
              WHEN 7,31,32,8,11: IF FNicon_set(xbuff%!32,xbuff%!36)pdf_s$+="b" ELSE pdf_s$+="a"
            ENDCASE
            pdf_t$=FNmsg_0(psup%!CONST_psup_msg,"CON"+pdf_s$)
            IF pdf_t$="CON"+pdf_s$ pdf_t$=FNmsg_0(psup%!CONST_psup_msg,"CON")
            PROCinteractive_help(pdf_t$)
        ENDCASE
        wind%=0
      ELSE
        wind%=wind%!CONST_wind_next
        IF wind%=0 THEN
          REM must be a menu
          PROCinteractive_help(FNmsg_0(psup%!CONST_psup_msg,"H"+pdf_menu_chsn$))
        ENDIF
      ENDIF
    ENDWHILE
  WHEN &8014C: IF prnt%=0 THEN
      xbuff%!12=xbuff%!8
      xbuff%!16=&80151: REM PSPrinterNotPS
      SYS"Wimp_SendMessage",17,xbuff%,xbuff%!4
    ELSE
      IF prnt%!CONST_prnt_psup<>psup% THEN
        xbuff%!12=xbuff%!8
        xbuff%!16=&80151: REM PSPrinterNotPS
        SYS"Wimp_SendMessage",17,xbuff%,xbuff%!4
      ELSE
        REM everything checks out. Calculate the size required then send
        REM the acknowledgement BEFORE doing the transfer block as this
        REM then gives us our task handle!
        pdf_s$="": IF prnt%!CONST_prnt_name pdf_s$=$prnt%!CONST_prnt_name
        pdf_t$="": IF prnt%!CONST_prnt_type pdf_t$=$prnt%!CONST_prnt_type
        pdf_f$="PrinterChoices:pdf.Printers."+STR$ !cnfg%!CONST_cnfg_pdf_fonts
        PROCpdf_ensure_dir
        size%=LEN pdf_s$+LEN pdf_t$+LEN pdf_f$+3
        recv%=xbuff%!4
        xbuff%!24=size%
        xbuff%!12=xbuff%!8
        xbuff%!16=&8014D: REM PSPrinterAck
        SYS"Wimp_SendMessage",17,xbuff%,recv%
        IF xbuff%!20 THEN
          dest%=xbuff%!20
          $buff%=pdf_s$+CHR$ 0
          SYS"Wimp_TransferBlock",xbuff%!4,buff%,recv%,dest%,LEN pdf_s$+1
          dest%+=LEN pdf_s$+1
          $buff%=pdf_t$+CHR$ 0
          SYS"Wimp_TransferBlock",xbuff%!4,buff%,recv%,dest%,LENpdf_t$+1
          dest%+=LEN pdf_t$+1
          $buff%=pdf_f$+CHR$ 0
          SYS"Wimp_TransferBlock",xbuff%!4,buff%,recv%,dest%,LENpdf_f$+1
        ENDIF
      ENDIF
    ENDIF
  WHEN &8014E: PROCpdf_try_to_find_fonts(prnt%)
  WHEN &8014F: PROCpdf_create_default_font_file
    PROCpdf_ensure_fonts(prnt%,FALSE)
    PROCpdf_add_fonts(FALSE)
    xbuff%!12=xbuff%!8
    xbuff%!16=&80150: REM PSPrinterDefaulted
    SYS"Wimp_SendMessage",17,xbuff%,xbuff%!4
  ENDCASE
  REM VDU: PROCftracef("PROCpdf_p17 done")
ENDPROC

DEF FNpdf_get_feed_name(f$)
  LOCAL pdf_c%, pdf_s$
  pdf_c%=OPENIN(f$):IFpdf_c%=0 :=""
  pdf_s$=GET$#pdf_c%:CLOSE#pdf_c%
  IFLEFT$(pdf_s$,19)="%%RISCOS_FeedName: " THEN :=MID$(pdf_s$,20)
  =""

DEF PROCpdf_create_default_font_file
  LOCAL pdf_c%,pdf_d%,pdf_t%,pdf_i%,prdt%
  REM VDU: PROCftracef("PROCpdf_create_default_font_file")
  pdf_i%=A%!CONST_interface_scratch
/*
 * REM we don't know where "ps" lives on the Printers path
 * REM and we can't write to it yet 'cos the font file
 * REM doesn't exist, so we have to canonicalise it
 */
  PROCpdf_ensure_dir
  SYS"OS_FSControl",37,"PrinterChoices:pdf.Printers",pdf_i%,,,128
  pdf_t%=pdf_i%: WHILE ?pdf_t%: pdf_t%+=1: ENDWHILE
  REM add the name of the font file onto the end of the path string
  $pdf_t%="."+STR$ !cnfg%!CONST_cnfg_pdf_fonts
  REM and create the file
  pdf_c%=OPENOUT $pdf_i%
  IF pdf_c% THEN
   REM point pdf_d% at the font list PRDT block
   prdt%=FNprinter_find_prdata_entry(psup%,$prnt%!CONST_prnt_type)
   pdf_d%=FNprinter_read_integer_entry(prdt%,CONST_pdf_template_fontalias)
   REM now point at the head of the LSTD list
   pdf_d%=pdf_d%!CONST_prdt_1st
   WHILE pdf_d%
    BPUT#pdf_c%,$pdf_d%!8+" "+$pdf_d%!12+" "+$pdf_d%!16
    pdf_d%=pdf_d%!CONST_lstd_next
   ENDWHILE
   CLOSE#pdf_c%
   SYS "XOS_File",4,$pdf_i%,,,,&13 /*attributes to WR/r*/
  ENDIF
ENDPROC

DEF PROCpdf_try_to_find_fonts(prnt%)
/*
 * REM when the user clicks on SAVE in !FontPrint, we can't
 * REM just go and find the fonts, 'cos the download window might
 * REM already be open for another printer
 */
  LOCAL pdf_i%,pdf_j%
  REM VDU: PROCftracef("PROCpdf_try_to_find")
  REM is the download window open?
  pdf_i%=psup%!CONST_psup_wind
  WHILE pdf_i%
   IF $(pdf_i%+CONST_wind_name)="download" THEN
    REM is the window open?
    !buff%=pdf_i%!CONST_wind_hand: SYS"Wimp_GetWindowState",,buff%
    IF buff%!32 AND 1<<16 THEN
     REM try to find this prnt either from the window
     REM or from later on in the linked list
     pdf_j%=pdf_i%!CONST_wind_prnt
     WHILE pdf_j%
      IF pdf_j%=prnt% ENDPROC: REM found - will be dealt with in due course
      pdf_j%=pdf_j%!CONST_prnt_next
     ENDWHILE
    ENDIF
    REM not found or window closed ... change the window to point
    REM to THIS prnt since it must be earlier in the linked list
    PROCpdf_find_fonts_to_do(prnt%)
    ENDPROC
   ELSE
    pdf_i%=pdf_i%!CONST_wind_next
   ENDIF
  ENDWHILE
ENDPROC

DEF PROCpdf_find_fonts_to_do(prnt%)
  REM VDU: PROCftracef("PROCpdf_find_fonts_to_do")
  WHILE prnt%
/*
 *  REM if we've got a printer in our class - compare the font file with our
 *  REM idea of what needs to be done
 */
   IF prnt%!CONST_prnt_psup=psup% PROCpdf_ensure_fonts(prnt%,TRUE)
   prnt%=prnt%!CONST_prnt_next
  ENDWHILE
ENDPROC

DEF PROCpdf_ensure_fonts(prnt%,take_action%)
  LOCAL pdf_i%,pdf_j%,pdf_k%,pdf_s$,pdf_t$,pdf_e$,pdf_download%,pdf_changed%
  REM VDU: PROCftracef("PROCpdf_ensure_fonts")
  cnfg%=prnt%!CONST_prnt_cnfg
  pdf_download%=FALSE: REM nothing to download yet
  pdf_changed%=FALSE
  REM set all the flags to show no matches against the file
  pdf_j%=prnt%!CONST_prnt_fonts
  PROCpdf_ensure_dir
  WHILE pdf_j%
   pdf_j%!CONST_fonts_flags=pdf_j%!CONST_fonts_flags OR 1<<30
   IF pdf_j%!CONST_fonts_flags AND 1<<31 THEN
/*    REM we've got a font to download from an earlier attempt */
    pdf_download%=TRUE
    pdf_changed%=TRUE
   ENDIF
   pdf_j%=pdf_j%!CONST_fonts_next
  ENDWHILE
  pdf_i%=OPENIN("PrinterChoices:pdf.Printers."+STR$ !cnfg%!CONST_cnfg_pdf_fonts)
  IF pdf_i%=0 THEN
   PROCpdf_create_default_font_file
   pdf_i%=OPENIN("PrinterChoices:pdf.Printers."+STR$ !cnfg%!CONST_cnfg_pdf_fonts)
  ENDIF
  IF pdf_i% THEN
   WHILE NOTEOF#pdf_i%
    REM marry up the contents of the file against the current list
    pdf_s$=GET$#pdf_i%: pdf_t$="": pdf_e$=""
    pdf_j%=INSTR(pdf_s$," ")
    IF pdf_j%<>0 THEN
     pdf_t$=MID$(pdf_s$,pdf_j%+1)
     pdf_s$=LEFT$(pdf_s$,pdf_j%-1)
     pdf_k%=INSTR(pdf_t$," ")
     IF pdf_k%<>0 THEN
      pdf_e$=MID$(pdf_t$,pdf_k%+1)
      pdf_t$=LEFT$(pdf_t$,pdf_k%-1)
     ENDIF
    ENDIF
    pdf_s$="\F"+pdf_s$: IF pdf_e$<>"" pdf_s$+="\E"+pdf_e$
    pdf_k%=prnt%!CONST_prnt_fonts
    WHILE pdf_k%>0
     IF pdf_k%!CONST_fonts_foreign pdf_e$=$pdf_k%!CONST_fonts_foreign ELSE pdf_e$=""
     IF $pdf_k%!CONST_fonts_acorn=pdf_s$ AND pdf_e$=pdf_t$ THEN
      REM matched this entry in the file
      pdf_k%!CONST_fonts_flags=pdf_k%!CONST_fonts_flags AND NOT(1<<30)
      pdf_k%=-1
     ELSE
      pdf_k%=pdf_k%!CONST_fonts_next
     ENDIF
    ENDWHILE
    IF pdf_k%=0 THEN
     REM got to add font to list
     pdf_changed%=TRUE
     B%=CONST_ident_FONT
     C%=CONST_fonts_MAX
     pdf_k%=USR(code_entry%+CONST_entry_heap_claim)
     IFpdf_k%=0 ERROR CONST_error_fatal, FNmsg_0(FNpdf_host_desc,"FA5")
     pdf_k%!CONST_fonts_next=prnt%!CONST_prnt_fonts: prnt%!CONST_prnt_fonts=pdf_k%
     $buff%=pdf_s$: B%=buff%: C%=2: pdf_k%!CONST_fonts_acorn=USR(code_entry%+CONST_entry_store_string)
     REM VDU: PROCftracef("Length of block for '"+$buff%+"' is &"+STR$~(!((pdf_k%!CONST_fonts_acorn)-8)))
     $buff%=pdf_t$: B%=buff%: C%=2: pdf_k%!CONST_fonts_foreign=USR(code_entry%+CONST_entry_store_string)
     REM VDU: PROCftracef("Length of block for '"+$buff%+"' is &"+STR$~(!((pdf_k%!CONST_fonts_foreign)-8)))
     pdf_k%!CONST_fonts_flags=1
     IF pdf_j%=0 THEN
      pdf_download%=TRUE: REM got SOMETHING to download
      pdf_k%!CONST_fonts_flags=pdf_k%!CONST_fonts_flags OR 1<<31
     ENDIF
    ENDIF
   ENDWHILE
   CLOSE#pdf_i%
   PROCpdf_lose_fonts
   IF pdf_changed% AND take_action% THEN
    IF pdf_download% THEN
     pdf_i%=FNprinter_find_window(prnt%,"download")
     PROCicon_write(pdf_i%,3,FNprinter_read_string(prnt%!CONST_prnt_name))
     PROCicon_write(pdf_i%,4,$prnt%!CONST_prnt_type)
     PROCicon_write(pdf_i%,5,"0"): REM The default password for PostScript
     !buff%=pdf_i%: SYS"Wimp_GetWindowState",,buff%
     SYS"Wimp_OpenWindow",,buff%
     PROCcaret_set(pdf_i%,5): REM get caret at end of string
     REM was SYS"Wimp_SetCaretPosition",pdf_i%,5,-1,-1,-1,0
     ENDPROC
    ELSE
     IF prnt%!CONST_prnt_flags AND 2 THEN
/*
 *     REM this is the currently selected printer so re-ensure it 'cos the
 *     REM mappings have changed
 */
      !buff%=20: buff%!12=0: buff%!16=&80152: SYS"Wimp_SendMessage",17,buff%,0
     ENDIF
    ENDIF
   ENDIF
  ELSE
   PROCpdf_lose_fonts
  ENDIF
ENDPROC

DEF PROCpdf_download_fonts(wind%)
  LOCAL pdf_i%,pdf_c%,pdf_j%,pdf_k%,pdf_l%,pdf_s$,B%,C%,D%,E%,F%,G%,ptr%
  LOCAL ERROR
  REM VDU: PROCftracef("PROCpdf_download_fonts")
  REM Check that there is a password.
  IF FNicon_read(wind%,5)="" ERROR CONST_error_ok,FNmsg_0(psup%!CONST_psup_msg,"OK0")
  SYS"Hourglass_On"
  REM need to find a file to spit the data into
  pdf_i%=0
  REPEAT
   SYS"OS_File",17,"<Wimp$ScrapDir>.Printers."+STR$ pdf_i% TO pdf_c%
   IF pdf_c% pdf_i%+=1
  UNTIL pdf_c%=0
  REM now select the PostScript driver module
  SYS"PDriver_SelectDriver",8
  PROCpdf_add_fonts(TRUE): REM declare the MAPPED fonts
  pdf_c%=OPENOUT("<Wimp$ScrapDir>.Printers."+STR$ pdf_i%)
  ON ERROR LOCAL RESTORE ERROR: CLOSE#pdf_c%: ERROR ERR,REPORT$
  BPUT#pdf_c%,"%!PS-Adobe-2.0 ExitServer"
  BPUT#pdf_c%,"%%Creator: "+FNmsg_0(psup%!CONST_psup_msg,"ID")
  BPUT#pdf_c%,"%%CreationDate: ";
  ?buff%=3: SYS"OS_Word",14,buff%
  SYS"OS_ConvertStandardDateAndTime",buff%,buff%+5,250: pdf_k%=buff%+5
  WHILE ?pdf_k% BPUT#pdf_c%,?pdf_k%: pdf_k%+=1: ENDWHILE: BPUT#pdf_c%,10
  BPUT#pdf_c%,"%%DocumentSuppliedFonts: ";
  pdf_j%=prnt%!CONST_prnt_fonts: pdf_l%=FALSE
  WHILE pdf_j%
   IF pdf_j%!CONST_fonts_flags AND 1<<31 THEN
    SYS "MakePSFont_MakeFont",-2,$pdf_j%!CONST_fonts_acorn+CHR$ 0,buff%,256,0
    IF pdf_l% BPUT#pdf_c%,"%%+ ";
    pdf_k%=buff%: pdf_l%=TRUE
    WHILE ?pdf_k% BPUT#pdf_c%,?pdf_k%: pdf_k%+=1: ENDWHILE
    BPUT#pdf_c%,10
   ENDIF
   pdf_j%=pdf_j%!CONST_fonts_next
  ENDWHILE
  BPUT#pdf_c%,"%%Pages: 0"
  BPUT#pdf_c%,"%%BoundingBox: 0 0 0 0"
  BPUT#pdf_c%,"%%EndComments"
  BPUT#pdf_c%,"%%BeginSetup"
  BPUT#pdf_c%,"%%BeginExitServer: "+FNicon_read(wind%,5)
  BPUT#pdf_c%,"serverdict begin "+FNicon_read(wind%,5)+" exitserver"
  BPUT#pdf_c%,"%%EndExitServer"
  BPUT#pdf_c%,"%%EndSetup"
  pdf_j%=prnt%!CONST_prnt_fonts
  WHILE pdf_j%
   IF pdf_j%!CONST_fonts_flags AND 1<<31 THEN
    SYS "MakePSFont_MakeFont",pdf_c%,$pdf_j%!CONST_fonts_acorn+CHR$0,buff%,256,0
    pdf_j%!CONST_fonts_flags=pdf_j%!CONST_fonts_flags AND NOT(1<<31)
   ENDIF
   pdf_j%=pdf_j%!CONST_fonts_next
  ENDWHILE
  BPUT#pdf_c%,"%%EOF"
  CLOSE#pdf_c%
  RESTORE ERROR
  SYS"OS_File",18,"<Wimp$ScrapDir>.Printers."+STR$ pdf_i%,&FF5
  REM re-select the default printer so that the font settings are true
  !buff%=20: buff%!12=0: buff%!16=&80152: SYS"Wimp_SendMessage",17,buff%,0
/*
 * REM we use xbuff here ... this is safe 'cos this procedure gets called
 * REM as a result of a keypress or window close.
 */
  B%=TRUE
  C%=xbuff%: $C%=FNmsg_0(psup%!CONST_psup_msg,"PR")
  D%=C%+LEN $C%+1: $D%="<Wimp$ScrapDir>.Printers."+STR$ pdf_i%
  E%=D%+LEN $D%+1: $E%=FNmsg_0(psup%!CONST_psup_msg,"DF")
  F%=prnt%
  G%=&FF5
  CALL code_entry%+CONST_entry_add_queue_entry
  PROCpdf_find_fonts_to_do(prnt%!CONST_prnt_next)
  SYS"Hourglass_Off"
  REM VDU: PROCftracef("PROCpdf_download_fonts done")
ENDPROC

DEF PROCpdf_lose_fonts
  LOCAL pdf_i%,pdf_old_i%
  REM VDU: PROCftracef("PROCpdf_lose_fonts")
  pdf_i%=prnt%!CONST_prnt_fonts
  WHILE pdf_i%
   IF pdf_i%!CONST_fonts_flags AND 1<<30 THEN
    REM make the link
    IF pdf_old_i% THEN
     pdf_old_i%!CONST_fonts_next=pdf_i%!CONST_fonts_next
    ELSE
     prnt%!CONST_prnt_fonts=pdf_i%!CONST_fonts_next
    ENDIF
    B%=CONST_ident_STRG: C%=pdf_i%!CONST_fonts_acorn: CALL code_entry%+CONST_entry_heap_free
    B%=CONST_ident_STRG: C%=pdf_i%!CONST_fonts_foreign: CALL code_entry%+CONST_entry_heap_free
    B%=CONST_ident_FONT: C%=pdf_i%: pdf_i%=pdf_i%!CONST_fonts_next: CALL code_entry%+CONST_entry_heap_free
   ELSE
    pdf_old_i%=pdf_i%
    pdf_i%=pdf_i%!CONST_fonts_next
   ENDIF
  ENDWHILE
ENDPROC

DEF PROCpdf_add_fonts(only_mapped%)
  LOCAL pdf_i%,pdf_j%,pdf_old_driver%
  REM VDU: PROCftracef("PROCpdf_add_fonts")
  SYS"PDriver_SelectDriver",8 TO pdf_old_driver%
  SYS"PDriver_MiscOp",1: REM clear all fonts
  pdf_i%=prnt%!CONST_prnt_fonts
  WHILE pdf_i%
   pdf_j%=pdf_i%!CONST_fonts_flags AND NOT(3<<30): REM lose our private bits
   IF pdf_i%!CONST_fonts_foreign=0 THEN
    IF only_mapped%=FALSE THEN
     REM a downloaded font - need to call MakePSFont in case derived fonts are needed
     REM note that -1 means no output generated
     SYS "MakePSFont_MakeFont",-1,$pdf_i%!CONST_fonts_acorn+CHR$ 0,buff%,256,0
    ENDIF
   ELSE
    REM a remap - just declare it
    SYS"PDriver_MiscOp",0,$pdf_i%!CONST_fonts_acorn,$pdf_i%!CONST_fonts_foreign,pdf_j%
   ENDIF
   pdf_i%=pdf_i%!CONST_fonts_next
  ENDWHILE
  SYS"PDriver_SelectDriver",pdf_old_driver%
  REM VDU: PROCftracef("PROCpdf_add_fonts done")
ENDPROC

DEF PROCpdf_save_configuration(window%)
  LOCAL pdf_i%,pdf_j%,pdf_k%,pdf_s$,B%,C%,pdf_t$
  REM VDU: PROCftracef("PROCpdf_save_configuration_window")
  prdt%=FNprinter_find_prdata_entry(psup%,FNicon_read(window%,6))
  PROCfree_structure(prnt%!CONST_prnt_name)
  $buff%=FNicon_read(window%,13)
  B%=buff%
  C%=2
  prnt%!CONST_prnt_name=USR(code_entry%+CONST_entry_store_string)

  IF cnfg%!CONST_cnfg_pdf_feed <> 0 THEN
    PROCfree_structure(cnfg%!CONST_cnfg_pdf_feed)
    cnfg%!CONST_cnfg_pdf_feed=0
  ENDIF
  pdf_i%=0
  pdf_t$=FNprinter_read_string_entry(prdt%,CONST_pdf_template_feeds)
  REM if the default setting has been chosen, do not save anything away
  IFpdf_t$<>FNmsg_0(psup%!CONST_psup_msg,"ME1b") AND pdf_t$<>"" THEN
    REM otherwise match up on the feed name
    REPEAT
      SYS"OS_GBPB",9,pdf_t$,buff%,1,pdf_i%,256,"*" TO ,,,pdf_j%
      IFpdf_j%=1 THEN
        CALL Z%,buff%,pdf_s$
        $buff%=pdf_t$+"."+pdf_s$
        IFFNpdf_get_feed_name($buff%)=FNicon_read(window%,3) THEN
          B%=buff%
          C%=2
          cnfg%!CONST_cnfg_pdf_feed=USR(code_entry%+CONST_entry_store_string)
          pdf_i%=-1
        ELSE
          pdf_i%+=1
        ENDIF
      ENDIF
    UNTIL pdf_j%<>1 OR pdf_i%<0
  ENDIF

  pdf_j%=0
  IF FNicon_set(window%,8)                                                                       pdf_j%+=1
  IF FNicon_set(window%,11)                                                                      pdf_j%+=2
  IF FNicon_read(window%,18)=FNmsg_0(psup%!CONST_psup_msg,"PO1")                                 pdf_j%+=4
  IF cnfg%!CONST_cnfg_pdf_feed = 0 AND FNicon_read(window%,3)=FNmsg_0(psup%!CONST_psup_msg,"PF1") pdf_j%+=8
  IF FNicon_set(window%,7)                                                                       pdf_j%+=16
  IF FNicon_set(window%,31)                                                                      pdf_j%+=32
  IF FNicon_set(window%,32)                                                                      pdf_j%+=64
  pdf_i%=VAL FNicon_read(window%,30)
  IF pdf_i%>200 pdf_i%=100
  IF pdf_i%<20  pdf_i%=100
  pdf_j%+=pdf_i%<<8
  pdf_j%+=VAL FNicon_read(window%,16)-1<<16
  CASE FNicon_read(window%,23)OF
    WHEN FNmsg_0(psup%!CONST_psup_msg,"CC1"): pdf_j%+=1<<24
    WHEN FNmsg_0(psup%!CONST_psup_msg,"CC2"): pdf_j%+=1<<25
  ENDCASE
  !cnfg%!CONST_cnfg_pdf_flags=pdf_j%

  pdf_j%=prnt%!CONST_prnt_psze: pdf_s$=FNicon_read(window%,27)
  IF $pdf_j%!CONST_psze_name<>pdf_s$ THEN
   pdf_i%=psize_head%
   WHILE pdf_i%
    IF $pdf_i%!CONST_psze_name=pdf_s$ THEN
     prnt%!CONST_prnt_psze=pdf_i%
     pdf_i%=0
    ELSE
     pdf_i%=pdf_i%!CONST_psze_next
    ENDIF
   ENDWHILE
  ENDIF

  IF prnt%!CONST_prnt_icon<>-1 THEN
    REM this printer is ACTIVE!
    REM ensure that its details are correct
    PROCselect_printer(prnt%,TRUE,FALSE)
    REM The front end code will spot that the selected printer has
    REM changed and put everything back the way it was
    REM PROCselect_printer(0,TRUE,TRUE): REM don't do this (calls into overlay). JRC 12 Feb '92
  ENDIF
ENDPROC

DEF PROCpdf_menu(top$,rebuild%,iconpos%)
  LOCAL wind%,pdf_i%,pdf_ix%,pdf_iy%,ind_title%,list_index%,menu_index%,s$,t$
  REM VDU: PROCftracef("PROCpdf_menu")
  IF rebuild% THEN
   pdf_menu_xpos%=xbuff%!0-64
   pdf_menu_ypos%=xbuff%!4
  ENDIF
  IF iconpos% THEN
   !buff%=xbuff%!12: buff%!4=xbuff%!16: SYS"Wimp_GetIconState",,buff%
   pdf_ix%=buff%!16: pdf_iy%=buff%!20
   SYS"Wimp_GetWindowState",,buff%
   pdf_menu_xpos%=buff%!20+buff%!4+pdf_ix%+2
   pdf_menu_ypos%=buff%!24+buff%!16+pdf_iy%-2
  ENDIF
  wind%=FNprinter_find_window(prnt%,"configure")
  pdf_menu_chsn$=top$
  CASE top$ OF
  WHEN "ME1": IF FNprinter_read_string_entry(prdt%,CONST_pdf_template_feeds)="" THEN
                PROCmenu_create(pdf_menu%,FNmsg_0(psup%!CONST_psup_msg,"ME1a"))
              ELSE
                PROCmenu_create(pdf_menu%,FNmsg_0(psup%!CONST_psup_msg,"ME1")+","+FNmsg_0(psup%!CONST_psup_msg,"ME1b")+"#")
                ind_title%=(pdf_menu%!28 AND &100)<>0
                /* scan the list of available paper feeds */
                list_index%=0
                menu_index%=1:REM add items after default entry
                t$=FNprinter_read_string_entry(prdt%,CONST_pdf_template_feeds)
                SYS"Hourglass_On"
                REPEAT
                  SYS"OS_GBPB",9,t$,buff%,1,list_index%,256,"*" TO ,,,pdf_i%
                  IFpdf_i%=1 THEN
                    CALL Z%,buff%,s$
                    s$=FNpdf_get_feed_name(t$+"."+s$)
                    IFs$<>"" PROCmenu_item(pdf_menu%,menu_index%,s$,ind_title%):menu_index%+=1
                    list_index%+=1
                  ENDIF
                UNTIL pdf_i%<>1
                SYS"Hourglass_Off"
              ENDIF
              PROCmenu_tick_match(pdf_menu%,FNicon_read(wind%,3))
  WHEN "ME2": PROCmenu_create(pdf_menu%,FNmsg_0(psup%!CONST_psup_msg,"ME2"))
              PROCmenu_tick_match(pdf_menu%,FNicon_read(wind%,16))
  WHEN "ME3": PROCmenu_create(pdf_menu%,FNmsg_0(psup%!CONST_psup_msg,"ME3"))
              PROCmenu_tick_match(pdf_menu%,FNicon_read(wind%,18))
  WHEN "ME4": PROCmenu_create(pdf_menu%,FNmsg_0(psup%!CONST_psup_msg,"ME4"))
              PROCmenu_tick_match(pdf_menu%,FNicon_read(wind%,23))
  WHEN "MP1": PROCcreate_paper_menu(pdf_menu%,wind%,27)
  ENDCASE
  PROCdisplay_menu(prnt%,pdf_menu%,pdf_menu_xpos%,pdf_menu_ypos%)
ENDPROC

  REM Text printing code

DEF PROCpdf_m8
  LOCAL pdf_r%,queu%,tpub%,tprv%
  REM VDU: PROCftracef("PROCpdf_m8")
  pdf_r%=!xbuff%
  queu%=xbuff%!4
  tpub%=queu%!CONST_queu_tpub
  tprv%=queu%!CONST_queu_tprv
  CASE pdf_r% OF
  WHEN -1: PROCpdf_1
  WHEN -2: PROCpdf_2
  WHEN -3: PROCpdf_3
  WHEN -4: PROCpdf_4
  WHEN -6: PROCpdf_6
  WHEN -7: PROCpdf_7
  WHEN -8: PROCpdf_8
  WHEN -9: PROCpdf_9
  WHEN-10: PROCpdf_10
  WHEN-11: PROCpdf_11
  WHEN-12: PROCpdf_12
  WHEN-13: PROCpdf_13
  WHEN-14: PROCpdf_14
  WHEN-15: PROCpdf_15
  WHEN-16: PROCpdf_16
  WHEN-17: PROCpdf_17
  WHEN-18: PROCpdf_18
  WHEN-19: PROCpdf_19
  WHEN-20: PROCpdf_20
  ENDCASE
ENDPROC

DEF PROCpdf_1
/*  REM only called if we aren't printing a PostScript file */
  LOCAL local_pl%,local_pr%,local_pb%,local_pt%,local_margin%
  LOCAL local_psze%,local_format_print%,local_pw%
  LOCAL last_char%
  LOCAL pdf_i%,pdf_s$,pdf_h,pdf_w,B%,C%
  REM VDU: PROCftracef("PROCpdf_1")
/*  REM this is the first call to us, so let's claim our private text block */
  B%=CONST_ident_TPRV: C%=CONST_tprv_pdf_MAX
  tprv%=USR(code_entry%+CONST_entry_heap_claim)
  IFtprv%=0 ERROR CONST_error_fatal, FNmsg_0(FNpdf_host_desc,"FA5")
  queu%!CONST_queu_tprv=tprv%
  FORpdf_i%=CONST_tprv_pdf_bbox TO CONST_tprv_pdf_right_print STEP 4: tprv%!pdf_i%=0: NEXT
  REM
  local_format_print%=(!cnfg%!CONST_cnfg_pdf_flags AND 4)>>2
  tprv%!CONST_tprv_pdf_cols_print=1+((!cnfg%!CONST_cnfg_pdf_flags AND &FF0000)>>16)
  tpub%!CONST_tpub_number_print=(!cnfg%!CONST_cnfg_pdf_flags AND 2)>>1
  tpub%!CONST_tpub_title_print=!cnfg%!CONST_cnfg_pdf_flags AND 1
  IF queu%!CONST_queu_type=&FFF THEN
   tpub%!CONST_tpub_cc_print=(!cnfg%!CONST_cnfg_pdf_flags AND &FF000000)>>24
  ELSE
   tpub%!CONST_tpub_cc_print=(!cnfg%!CONST_cnfg_pdf_flags AND &FF000000)>>24: REM was 1 JRC
  ENDIF
  local_margin%=50
  local_psze%=prnt%!CONST_prnt_psze
  local_pl%=local_psze%!CONST_psze_lmargin DIV 100 + 1 + local_margin%
  local_pr%=local_psze%!CONST_psze_rmargin DIV 100 - local_margin%
  local_pb%=local_psze%!CONST_psze_bmargin DIV 100 + 1 + local_margin%
  local_pt%=local_psze%!CONST_psze_tmargin DIV 100 - local_margin%
  pdf_s$=STR$(local_pl% DIV 10)+" "+STR$(local_pb% DIV 10)
  pdf_s$+=" "+STR$((local_pr%+9)DIV 10)+" "+STR$((local_pt%+9)DIV 10)
  $buff%=pdf_s$: B%=buff%: C%=2: tprv%!CONST_tprv_pdf_bbox=USR(code_entry%+CONST_entry_store_string)
  IF local_format_print%=0 THEN
   REM portrait
   IF tpub%!CONST_tpub_title_print local_pt%-=150
   local_pw%=local_pr%-local_pl%
   tprv%!CONST_tprv_pdf_ph=local_pt%-local_pb%
   $buff%=STR$ local_pl%+" "+STR$ local_pt%+" 0"
  ELSE
   REM landscape
   IF tpub%!CONST_tpub_title_print local_pl%+=150
   local_pw%=local_pt%-local_pb%
   tprv%!CONST_tprv_pdf_ph=local_pr%-local_pl%
   $buff%=STR$ local_pb%+" "+STR$ -local_pl%+" 90"
  ENDIF

  B%=buff%: C%=2: tprv%!CONST_tprv_pdf_transform=USR(code_entry%+CONST_entry_store_string)
  tprv%!CONST_tprv_pdf_fsize=(!cnfg%!CONST_cnfg_pdf_flags AND &FF00)>>8
  REM VDU: PROCftracef("Local font size is "+STR$ tprv%!CONST_tprv_pdf_fsize)

  pdf_w=0.72*tprv%!CONST_tprv_pdf_fsize /*: REM courier character width is 60% of size. Also starring "hack." JRC 31 Mar '92 */
  pdf_h=1.2*tprv%!CONST_tprv_pdf_fsize: REM allow 10% leading

  REM VDU: PROCftracef("=> (w, h) = ("+STR$ pdf_w+", "+STR$ pdf_h+")")

  local_pw%=local_pw% DIV pdf_w: REM size of page in characters
  tprv%!CONST_tprv_pdf_ph=tprv%!CONST_tprv_pdf_ph DIV pdf_h
  tprv%!CONST_tprv_pdf_cw=(local_pw%+2)DIV tprv%!CONST_tprv_pdf_cols_print-2: REM width of column in characters

  IF tprv%!CONST_tprv_pdf_cw<10+local_psze%!CONST_psze_tleft+local_psze%!CONST_psze_tright THEN
    ERROR CONST_error_ok,FNmsg_0(psup%!CONST_psup_msg,"ErrNarr")
  ENDIF

  tprv%!CONST_tprv_pdf_mt=local_psze%!CONST_psze_ttop
  tpub%!CONST_tpub_line_max=tprv%!CONST_tprv_pdf_ph-local_psze%!CONST_psze_tbottom
  tprv%!CONST_tprv_pdf_left_print=local_psze%!CONST_psze_tleft
  tprv%!CONST_tprv_pdf_right_print=local_psze%!CONST_psze_tright
  tpub%!CONST_tpub_xc=tprv%!CONST_tprv_pdf_cw-tprv%!CONST_tprv_pdf_right_print
  tprv%!CONST_tprv_pdf_xl=tprv%!CONST_tprv_pdf_left_print

  IF tpub%!CONST_tpub_number_print tprv%!CONST_tprv_pdf_xl+=6

  REM build a character translation table
  PROCpdf_add_char(last_char%,40,"\(")
  PROCpdf_add_char(last_char%,41,"\)")
  PROCpdf_add_char(last_char%,92,"\\")
  FORpdf_i%=128 TO 255
   PROCpdf_add_char(last_char%,pdf_i%,FNpdf_oct(pdf_i%))
  NEXT
ENDPROC

DEF PROCpdf_add_char(RETURN last%,char%,trans$)
  LOCAL pdf_p%,B%,C%
  REM VDU: PROCftracef("PROCpdf_add_char")
  B%=CONST_ident_CHAR: C%=7+LEN trans$
  pdf_p%=USR(code_entry%+CONST_entry_heap_claim)
  IFpdf_p%=0 ERROR CONST_error_fatal, FNmsg_0(FNpdf_host_desc,"FA5")
  !pdf_p%=0
  pdf_p%?4=char%
  pdf_p%?5=LEN trans$
  $(pdf_p%+6)=trans$
  IF last% THEN
   !last%=pdf_p%
  ELSE
   queu%!CONST_queu_char=pdf_p%
  ENDIF
  last%=pdf_p%
ENDPROC

DEF PROCpdf_2
  REM Produce any required job initialisation output
  LOCAL pdf_c%
  REM VDU: PROCftracef("PROCpdf_2")
  pdf_c%=xbuff%!8
  PROCpdf_header(pdf_c%)
  PROCpdf_prolog(pdf_c%)
  PROCpdf_encoding(pdf_c%)
  PROCpdf_setupline(pdf_c%)
ENDPROC

DEF PROCpdf_header(pdf_c%)
  LOCAL pdf_old_job%,pdf_old_driver%,pdf_s$,pdf_i%
  REM VDU: PROCftracef("PROCpdf_header")
  REM need to ensure that PDriverPS is the selected driver
  SYS"PDriver_SelectDriver",8 TO pdf_old_driver%
  REM get PDriverPS to output the job header and start a job
  SYS"PDriver_SelectJob",pdf_c%,FNprinter_read_string(tpub%!CONST_tpub_name)TO pdf_old_job%
  REM now restore the old job
  SYS"PDriver_SelectJob",pdf_old_job%
  REM and the old driver
  SYS"PDriver_SelectDriver",pdf_old_driver%
  /* output the feed postscript here in case it redefines any words used later on, like showpage */
  IF cnfg%!CONST_cnfg_pdf_feed <> 0 THEN
    pdf_i%=OPENIN(FNprinter_read_string(cnfg%!CONST_cnfg_pdf_feed))
    IFpdf_i%<>0 THEN WHILE NOT EOF#pdf_i%:BPUT#pdf_c%,BGET#pdf_i%:ENDWHILE:CLOSE#pdf_i%
  ENDIF
  BPUT#pdf_c%,"/PDdict 50 dict def"
  BPUT#pdf_c%,"PDdict begin"
ENDPROC

DEF PROCpdf_encoding(pdf_c%)
  LOCAL pdf_f%,pdf_h%,pdf_old_driver%,pdf_b$,pdf_bo$,pdf_m$,pdf_mo$
  LOCAL pdf_acc%
  LOCAL ERROR
  REM VDU: PROCftracef("PROCpdf_encoding")
  REM SYS"XOS_Find",&40,"Printers:ps.PSfiles.PSencoding" TO pdf_h%;pdf_f%
  REM IF pdf_f% AND 1 pdf_h%=0
  REM IF pdf_h%=0 ERROR CONST_error_ok,FNmsg_0(psup%!CONST_psup_msg,"ErrEnc"): REM Error opening PSencoding file
  REM PROCpdf_outputfile(pdf_h%,pdf_c%)
  SYS"PDriver_SelectDriver",8 TO pdf_old_driver%
  SYS"PDriver_SelectJob",pdf_c% TO pdf_h%
  ON ERROR LOCAL RESTORE ERROR: SYS"PDriver_SelectJob",pdf_h%: ERROR ERR,REPORT$
  REM VDU: ON ERROR LOCAL RESTORE ERROR: SYS"PDriver_SelectJob",pdf_h%: ERROR ERR,REPORT$+" ("+STR$ ERL+")"

  REM if accented chars button checked, then use RF/RFE proc for remapping.  Otherwise send
  REM inline code, which does not do PostScript runtime accent generation.
  REM R4=16+4+1 means use RF and RFE procs to do the remap (supplied in prolog), that this is a
  REM non-permanent print job, and to make the extra declarations for DocumentFonts and DocumentSuppliedFonts

  IF !cnfg%!CONST_cnfg_pdf_flags AND 64 pdf_acc%=16+4+1 ELSE pdf_acc%=4+1

  SYS "MakePSFont_MakeFont",pdf_c%,"\FCorpus.Bold"+CHR$ 0,buff%,256,pdf_acc%: pdf_f%=buff%
  WHILE ?pdf_f%: pdf_b$+=CHR$ ?pdf_f%: pdf_f%+=1: ENDWHILE
  SYS "MakePSFont_MakeFont",pdf_c%,"\FCorpus.Bold.Oblique"+CHR$ 0,buff%,256,pdf_acc%: pdf_f%=buff%
  WHILE ?pdf_f%: pdf_bo$+=CHR$ ?pdf_f%: pdf_f%+=1: ENDWHILE
  SYS "MakePSFont_MakeFont",pdf_c%,"\FCorpus.Medium"+CHR$0,buff%,256,pdf_acc%: pdf_f%=buff%
  WHILE ?pdf_f%: pdf_m$+=CHR$ ?pdf_f%: pdf_f%+=1: ENDWHILE
  SYS "MakePSFont_MakeFont",pdf_c%,"\FCorpus.Medium.Oblique"+CHR$ 0,buff%,256,pdf_acc%: pdf_f%=buff%
  WHILE ?pdf_f%: pdf_mo$+=CHR$ ?pdf_f%: pdf_f%+=1: ENDWHILE

  REM now add these names to the DocumentFont list (within the job)
  SYS"XPDriver_MiscOp",0,pdf_m$,"X",40,0
  SYS"XPDriver_MiscOp",0,pdf_b$,"X",40,0
  SYS"XPDriver_MiscOp",0,pdf_mo$,"X",40,0
  SYS"XPDriver_MiscOp",0,pdf_bo$,"X",40,0
  SYS"PDriver_SelectJob",pdf_h%
  SYS"PDriver_SelectDriver",pdf_old_driver%
  BPUT#pdf_c%,"/TF /"+pdf_b$+" def"
  BPUT#pdf_c%,"/NF /"+pdf_m$+" def"
  BPUT#pdf_c%,"/BF /"+pdf_b$+" def"
  BPUT#pdf_c%,"/IF /"+pdf_mo$+" def"
  BPUT#pdf_c%,"/BIF /"+pdf_bo$+" def"
  BPUT#pdf_c%,10
ENDPROC

DEF PROCpdf_prolog(pdf_c%)
  LOCAL pdf_f%,pdf_h%
  REM VDU: PROCftracef("PROCpdf_prologue")
  SYS"XOS_Find",&4F,"Printers:ps.PSfiles.PStprolog" TO pdf_h%;pdf_f%
  IF pdf_f% AND 1 pdf_h%=0
  IF pdf_h%=0 ERROR CONST_error_ok,$(pdf_h%+4)
  PROCpdf_outputfile(pdf_h%,pdf_c%)
ENDPROC

DEF PROCpdf_outputfile(pdf_h%,pdf_c%)
  REM VDU: PROCftracef("PROCpdf_output")
  WHILE NOT EOF#pdf_h%
    BPUT#pdf_c%,GET$#pdf_h%
  ENDWHILE
  SYS"XOS_Find",0,pdf_h%
ENDPROC

DEF PROCpdf_setupline(pdf_c%)
  LOCAL pdf_s$, pdf_i%, local_psze%, pdf_extra$
  REM VDU: PROCftracef("PROCpdf_setupline")
  BPUT#pdf_c%,"%%EndProlog"
  BPUT#pdf_c%,"%%BeginSetup"

  local_psze%=prnt%!CONST_prnt_psze
  pdf_s$=$local_psze%!CONST_psze_name
  pdf_i%=0
  WHILE MID$(pdf_s$,pdf_i%,1)<>" " AND pdf_i%<=LEN pdf_s$
    pdf_i%+=1
  ENDWHILE
  pdf_s$=LEFT$(pdf_s$,pdf_i%-1)

  SYS"OS_File",17,"Printers:pdf.Paper."+FNtask_lower(pdf_s$) TO pdf_i%
  IF pdf_i%=1 THEN
    pdf_i%=OPENIN("Printers:pdf.Paper."+FNtask_lower(pdf_s$))
    IFpdf_i%<>0 THEN WHILE NOT EOF#pdf_i%:BPUT#pdf_c%,BGET#pdf_i%:ENDWHILE:CLOSE#pdf_i%
  ELSE
    pdf_extra$=FNmsg_2(psup%!CONST_psup_msg,"PT",pdf_s$,FNtask_lower(pdf_s$))
  ENDIF

  BPUT#pdf_c%, STR$(FNpdf_fontsize(tpub%!CONST_tpub_font_num))+" FI"

  IF FNprinter_read_string_entry(prdt%,CONST_pdf_template_feeds)="" AND cnfg%!CONST_cnfg_pdf_feed = 0 THEN
    IF !cnfg%!CONST_cnfg_pdf_flags AND 8 THEN
      pdf_s$=FNungstrans(FNprinter_read_boolean_string_entry(prdt%,CONST_pdf_template_manualfeed,TRUE))
    ELSE
      pdf_s$=FNungstrans(FNprinter_read_boolean_string_entry(prdt%,CONST_pdf_template_manualfeed,FALSE))
    ENDIF
    IF pdf_extra$<>"" pdf_extra$=pdf_s$+"|J"+pdf_extra$ ELSE pdf_extra$=pdf_s$
  ENDIF

  IF pdf_extra$<>"" THEN
    BPUT#pdf_c%,pdf_extra$
  ENDIF
  BPUT#pdf_c%,"%%EndSetup"
ENDPROC

DEF PROCpdf_3
  REM Produce page header
  LOCAL pdf_s$,old_pos%,local_psze%,local_style_bits%,pdf_c%,pdf_t$,pdf_w,pdf_h,@%
  REM VDU: PROCftracef("PROCpdf_3")
  local_style_bits%=tpub%!CONST_tpub_style_bits
  tpub%!CONST_tpub_style_bits=64: REM title bit
  pdf_c%=xbuff%!8
  pdf_s$="%%Page: "
  IF tprv%!CONST_tprv_pdf_cols_print>1 pdf_s$+=STR$(tprv%!CONST_tprv_pdf_cols_print*tpub%!CONST_tpub_page_num+1)+"-"
  tpub%!CONST_tpub_page_num+=1
  pdf_s$+=STR$(tprv%!CONST_tprv_pdf_cols_print*tpub%!CONST_tpub_page_num)+" "+STR$tpub%!CONST_tpub_page_num
  BPUT#pdf_c%,pdf_s$
  BPUT#pdf_c%,"%%PageBoundingBox: "+FNprinter_read_string(tprv%!CONST_tprv_pdf_bbox)
  BPUT#pdf_c%,FNprinter_read_string(tprv%!CONST_tprv_pdf_transform);
  BPUT#pdf_c%," "+STR$(1.2*tprv%!CONST_tprv_pdf_fsize);
  REM VDU: PROCftracef("Local font size is "+STR$(1.2*tprv%!CONST_tprv_pdf_fsize))
  pdf_w=0.72*tprv%!CONST_tprv_pdf_fsize: REM courier character width is 60% of size
  pdf_h=1.2*tprv%!CONST_tprv_pdf_fsize
  REM VDU: PROCftracef("=> (w, h) = ("+STR$ pdf_w+", "+STR$ pdf_h+")")

  @%="+g10.9"
  BPUT#pdf_c%," "+STR$ pdf_w+" "+STR$ pdf_h+" StartPage"
  IF tpub%!CONST_tpub_title_print THEN
    local_psze%=prnt%!CONST_prnt_psze
    old_pos%=tpub%!CONST_tpub_cpos
    pdf_s$=STR$(local_psze%!CONST_psze_ttop-0.5)+" "+STR$ tprv%!CONST_tprv_pdf_left_print+" MT "+STR$ 64+" ("
    pdf_t$=FNprinter_read_string(tpub%!CONST_tpub_name)+"   "+FNprinter_read_string(tpub%!CONST_tpub_time)
    pdf_t$+="   "+FNmsg_1(psup%!CONST_psup_msg,"PAG",STR$ tpub%!CONST_tpub_page_num)
    pdf_s$+=FNpdf_trans(pdf_t$)+") SS"
    BPUT#pdf_c%,pdf_s$
    tpub%!CONST_tpub_cpos=old_pos%
  ENDIF
  tpub%!CONST_tpub_style_bits=local_style_bits%
  tprv%!CONST_tprv_pdf_col=0
ENDPROC

DEF PROCpdf_4
  REM post line processing
  LOCAL pdf_i%,pdf_b$
  REM VDU: PROCftracef("PROCpdf_4")
  REM if we've output something and we aren't formatting, end the string
  IF xbuff%!8<>0 AND tpub%!CONST_tpub_format_flag=0 pdf_b$=") SS"
  REM if we've reached the end or we're ending the page ...
  IF EOF#queu%!CONST_queu_handle_in OR(tpub%!CONST_tpub_page_flag>1)THEN
    REM move on to the next column
    tprv%!CONST_tprv_pdf_col+=1
    REM if we've reached the end or we've run out of columns ...
    IF EOF#queu%!CONST_queu_handle_in OR tprv%!CONST_tprv_pdf_col>=tprv%!CONST_tprv_pdf_cols_print THEN
      REM set the stage to deal with the footer
      tpub%!CONST_tpub_stage=3
    ENDIF
  ENDIF
  xbuff%?8=LEN pdf_b$
  $(xbuff%+9)=pdf_b$
ENDPROC

DEF PROCpdf_6
  REMM Do control code processing
  LOCAL pdf_s$
  REM VDU: PROCftracef("PROCpdf_6")
  pdf_s$=FNpdf_display(xbuff%!8)
  xbuff%?8=LEN pdf_s$
  $(xbuff%+9)=pdf_s$
ENDPROC

DEF PROCpdf_7
  REM handle a backspace
  REM simple! just move back to where the last character is!
  LOCAL pdf_b$
  REM VDU: PROCftracef("PROCpdf_7")
  PROCpdf_8: REM stores its value in xbuff%+9
  pdf_b$=") SS "+$(xbuff%+9)
  xbuff%?8=LEN pdf_b$
  $(xbuff%+9)=pdf_b$
ENDPROC

DEF PROCpdf_8
  REM handle line splitting
  LOCAL pdf_b$,pdf_i
  REM VDU: PROCftracef("PROCpdf_8")
  pdf_i=tprv%!CONST_tprv_pdf_xl
  pdf_i+=tprv%!CONST_tprv_pdf_col*(tprv%!CONST_tprv_pdf_cw+1)
  pdf_i+=(tpub%!CONST_tpub_cpos-tprv%!CONST_tprv_pdf_xl)*(FNpdf_fontsize(0)/FNpdf_fontsize(tpub%!CONST_tpub_font_num))
  pdf_b$=STR$ tpub%!CONST_tpub_line_page+" "+STR$ pdf_i+" MT "+STR$(tpub%!CONST_tpub_style_bits AND &7F)+" ("
  xbuff%?8=LEN pdf_b$
  $(xbuff%+9)=pdf_b$
ENDPROC

DEF PROCpdf_9
  REM handle style changes
  LOCAL pdf_b$
  REM VDU: PROCftracef("PROCpdf_9")
  pdf_b$=") SS "+STR$(xbuff%!8 AND &7F)+" ("
  xbuff%?8=LEN pdf_b$
  $(xbuff%+9)=pdf_b$
ENDPROC

DEF PROCpdf_10
  REM start a new line
  LOCAL pdf_b$,line_num$,wrap%,pdf_i
  REM VDU: PROCftracef("PROCpdf_10")
  tpub%!CONST_tpub_line_page+=1
  tpub%!CONST_tpub_line_doc+=1
  pdf_i=tprv%!CONST_tprv_pdf_left_print+tprv%!CONST_tprv_pdf_col*(tprv%!CONST_tprv_pdf_cw+1)
  pdf_b$=STR$ tpub%!CONST_tpub_line_page+" "+STR$ pdf_i+" MT "
  wrap%=(tpub%!CONST_tpub_cpos>=tpub%!CONST_tpub_xc)
  IF tpub%!CONST_tpub_number_print THEN
    IF tpub%!CONST_tpub_font_num pdf_b$+=STR$ FNpdf_fontsize(0)+" FS "
    pdf_b$+="0 ("
    REM print line number, unless wrapped line
    IF wrap% THEN
      tpub%!CONST_tpub_line_doc-=1
      pdf_b$+=STRING$(6," ")
    ELSE
      line_num$=STR$ tpub%!CONST_tpub_line_doc
      pdf_b$+=STRING$(5-LEN line_num$," ")+line_num$+" "
    ENDIF
    tpub%!CONST_tpub_cpos=6
    pdf_b$+=") SS "
    IF tpub%!CONST_tpub_font_num pdf_b$+=STR$(FNpdf_fontsize(tpub%!CONST_tpub_font_num))+" FS "
  ELSE
    tpub%!CONST_tpub_cpos=0
  ENDIF
  IF tprv%!CONST_tprv_pdf_left_ruler>0 pdf_b$+="0 ("+STRING$(tprv%!CONST_tprv_pdf_left_ruler," ")+") SS "
  IF wrap% THEN
    tpub%!CONST_tpub_cpos+=1
    pdf_b$+="1 (|) SS ": REM print wrap bar in bold
  ENDIF
  pdf_b$+=STR$(tpub%!CONST_tpub_style_bits AND &7F)+" ("
  tpub%!CONST_tpub_cpos+=tprv%!CONST_tprv_pdf_left_print+tprv%!CONST_tprv_pdf_left_ruler
  xbuff%?8=LEN pdf_b$
  $(xbuff%+9)=pdf_b$
ENDPROC

DEF PROCpdf_11
  REM print footnote number
  LOCAL pdf_b$,pdf_i%
  REM VDU: PROCftracef("PROCpdf_11")
  PROCpdf_10: REM stores its value in xbuff%+9
  pdf_b$=$(xbuff%+9)+") SS "
  PROCpdf_10: pdf_b$+=$(xbuff%+9)+") SS "+STR$((tpub%!CONST_tpub_style_bits OR 1<<4)AND &7F)+" ("
  REM                                                        turn on superscript ^
  pdf_b$+=FNpdf_trans(RIGHT$("  "+STR$ tpub%!CONST_tpub_footnote_num,3))
  tpub%!CONST_tpub_cpos-=3
  pdf_b$+=") SS "
  PROCpdf_8: REM stores its value in xbuff%+9
  pdf_b$+=$(xbuff%+9)+CHR$92                   /* was: pdf_b$+=$(xbuff%+9)+"\"   AMcC: 20-Sep-92 */
  xbuff%?8=LEN pdf_b$
  $(xbuff%+9)=pdf_b$
ENDPROC

DEF PROCpdf_12
  REM string translation
  LOCAL pdf_b$
  REM VDU: PROCftracef("PROCpdf_12")
  pdf_b$=FNpdf_trans($(xbuff%+8))
  xbuff%?8=LEN pdf_b$
  $(xbuff%+9)=pdf_b$
ENDPROC

DEF PROCpdf_13
  REM handle font change
  LOCAL font_new%,pdf_b$,pdf_i%
  REM VDU: PROCftracef("PROCpdf_13")
  font_new%=xbuff%!8
  pdf_i%=tprv%!CONST_tprv_pdf_xl
  pdf_i%+=INT((tprv%!CONST_tprv_pdf_cw-tprv%!CONST_tprv_pdf_xl-tprv%!CONST_tprv_pdf_right_print)*FNpdf_fontsize(font_new%)/FNpdf_fontsize(0))
  tpub%!CONST_tpub_xc=pdf_i%
  tpub%!CONST_tpub_font_num=font_new%
  IF tpub%!CONST_tpub_left_new<tpub%!CONST_tpub_xc-tprv%!CONST_tprv_pdf_xl THEN
   tprv%!CONST_tprv_pdf_left_ruler=tpub%!CONST_tpub_left_new
  ELSE
   tprv%!CONST_tprv_pdf_left_ruler=0
  ENDIF
  IF tpub%!CONST_tpub_right_new<tpub%!CONST_tpub_xc-tprv%!CONST_tprv_pdf_xl AND tpub%!CONST_tpub_right_new>tprv%!CONST_tprv_pdf_left_ruler THEN
   tpub%!CONST_tpub_xc=tprv%!CONST_tprv_pdf_xl+tpub%!CONST_tpub_right_new
  ENDIF
  pdf_b$=STR$ FNpdf_fontsize(font_new%)+" FS"
  xbuff%?8=LEN pdf_b$
  $(xbuff%+9)=pdf_b$
ENDPROC

DEF PROCpdf_14
  REM finish page
  REM VDU: PROCftracef("PROCpdf_14")
  BPUT#xbuff%!8,"EndPage"
ENDPROC

DEF PROCpdf_15
  REM finish job
  LOCAL pdf_c%,cnct%,pdf_ptr%,pdf_ext%,pdf_data%,pdf_p%,B%,C%
  REM VDU: PROCftracef("PROCpdf_15")
  pdf_c%=xbuff%!8
  IF queu%!CONST_queu_type<>&FF5 THEN
   REM get the list of fonts ...
   REM (needs to be done before we end the job)
   SYS"PDriver_SelectJob",pdf_c% TO pdf_ext%
   SYS"PDriver_MiscOp",2,0,0,0,0 TO ,,C%
   IF C%<>0 THEN
    B%=CONST_ident_XXXX: pdf_data%=USR(code_entry%+CONST_entry_heap_claim)
    IFpdf_data%=0 ERROR CONST_error_fatal, FNmsg_0(FNpdf_host_desc,"FA5")
    SYS"PDriver_MiscOp",2,pdf_data%,C%,0,0
   ENDIF
   SYS"PDriver_SelectJob",pdf_ext%
/*
 *  REM we have to fudge this a little bit 'cos the printer driver wants
 *  REM to put its bit out, but we need to replace it
 */
   pdf_ptr%=PTR#pdf_c%: pdf_ext%=EXT#pdf_c%
   SYS"PDriver_EndJob",pdf_c%
   EXT#pdf_c%=pdf_ext%: PTR#pdf_c%=pdf_ptr%
   BPUT#pdf_c%,"%%Trailer"
   BPUT#pdf_c%,"end"
   BPUT#pdf_c%,"%%Pages: "+STR$ tpub%!CONST_tpub_page_num
   BPUT#pdf_c%,"%%BoundingBox: "+FNprinter_read_string(tprv%!CONST_tprv_pdf_bbox)
   IF C%<>0 THEN
    pdf_ptr%=PTR#pdf_c%: pdf_ext%=EXT#pdf_c%: BPUT#pdf_c%,"%%DocumentFonts: ";
    pdf_p%=pdf_data%
    REPEAT
     IF pdf_p%!8=40 OR pdf_p%!8=41 THEN
      B%=!pdf_p%
      WHILE ?B%: BPUT#pdf_c%,?B%: B%+=1: ENDWHILE: BPUT#pdf_c%,10
      pdf_ptr%=PTR#pdf_c%: pdf_ext%=EXT#pdf_c%: BPUT#pdf_c%,"%%+ ";
     ENDIF
     pdf_p%+=12
    UNTIL(pdf_p%-pdf_data%)>=C%
    EXT#pdf_c%=pdf_ext%: PTR#pdf_c%=pdf_ptr%
    pdf_ptr%=PTR#pdf_c%: pdf_ext%=EXT#pdf_c%: BPUT#pdf_c%,"%%DocumentSuppliedFonts: ";
    pdf_p%=pdf_data%
    REPEAT
      IF pdf_p%!8=41 THEN
        B%=!pdf_p%
        WHILE ?B%: BPUT#pdf_c%,?B%: B%+=1: ENDWHILE: BPUT#pdf_c%,10
        pdf_ptr%=PTR#pdf_c%: pdf_ext%=EXT#pdf_c%: BPUT#pdf_c%,"%%+ ";
      ENDIF
      pdf_p%+=12
    UNTIL pdf_p%-pdf_data%>=C%
    EXT#pdf_c%=pdf_ext%: PTR#pdf_c%=pdf_ptr%
    B%=CONST_ident_XXXX: C%=pdf_data%: CALL code_entry%+CONST_entry_heap_free
   ENDIF
  ENDIF
  cnct%=prnt%!CONST_prnt_cnct
  IF cnct%!CONST_cnct_type=1 OR cnct%!CONST_cnct_type=2 BPUT#pdf_c%,4
ENDPROC

DEF PROCpdf_16
  REM process a tab character
  LOCAL pdf_b$
  REM VDU: PROCftracef("PROCpdf_16")
  pdf_b$=STRING$(8-((tpub%!CONST_tpub_cpos-tprv%!CONST_tprv_pdf_left_print-tprv%!CONST_tprv_pdf_left_ruler+1-6*tpub%!CONST_tpub_number_print)MOD8)," ")
  tpub%!CONST_tpub_cpos+=LEN pdf_b$
  xbuff%?8=LEN pdf_b$
  $(xbuff%+9)=pdf_b$
ENDPROC

DEF PROCpdf_17
  REM no formfeed text ...
  REM VDU: PROCftracef("PROCpdf_17")
  xbuff%?8=0
ENDPROC

DEF PROCpdf_18
  REM change layout
  LOCAL layout_height%,layout_top%,layout_bottom%
  REM VDU: PROCftracef("PROCpdf_18")
  layout_height%=xbuff%!8
  layout_top%=xbuff%!12
  layout_bottom%=xbuff%!16
  IF layout_height%-layout_top%-layout_bottom%>3 AND layout_height%<=tprv%!CONST_tprv_pdf_ph THEN
   tpub%!CONST_tpub_line_max=layout_height%-layout_bottom%
   tprv%!CONST_tprv_pdf_mt=layout_top%
  ENDIF
  xbuff%?8=0
ENDPROC

DEF PROCpdf_19
  REM start new page
  REM VDU: PROCftracef("PROCpdf_19")
  tpub%!CONST_tpub_line_page=tprv%!CONST_tprv_pdf_mt
  xbuff%?8=0
ENDPROC

DEF PROCpdf_20
  REM prepend any code for a native (ie PostScript) file
  LOCAL pdf_c%, pdf_d%, pdf_i%, pdf_p%, pdf_q%
  REM VDU: PROCftracef("PROCpdf_20")
  pdf_c%=xbuff%!8
  pdf_d%=xbuff%!12
  IF cnfg%!CONST_cnfg_pdf_feed <>0 THEN
    pdf_i%=OPENIN(FNprinter_read_string(cnfg%!CONST_cnfg_pdf_feed))
    IFpdf_i%<>0 THEN
      REM copy %!PS-Adobe line
      PROCpdf_copy_line(pdf_d%, pdf_c%)
      REM now copy all of the %% lines
      REPEAT
        pdf_p%=BGET#pdf_d%:pdf_q%=BGET#pdf_d%:PTR#pdf_d%=PTR#pdf_d%-2
        IFpdf_p%=ASC"%" AND pdf_q%=ASC"%" PROCpdf_copy_line(pdf_d%, pdf_c%)
      UNTIL pdf_p%<>ASC"%" OR pdf_q%<>ASC"%"
      REM now copy the feed code
      WHILE NOT EOF#pdf_i%:BPUT#pdf_c%,BGET#pdf_i%:ENDWHILE
      CLOSE#pdf_i%
    ENDIF
  ENDIF
ENDPROC

DEF PROCpdf_copy_line(from%, to%)
  LOCAL pdf_c%
  REPEAT
    pdf_c%=BGET#from%
    BPUT#to%, pdf_c%
  UNTIL pdf_c%=10 OR pdf_c%=13
  REPEAT
    pdf_c%=BGET#from%
    IFpdf_c%=10 OR pdf_c%=13 BPUT#to%,pdf_c% ELSE PTR#from%=PTR#from%-1
  UNTIL pdf_c%<>10 AND pdf_c%<>13
ENDPROC

DEF FNpdf_fontsize(num%)
  REM provide notional cpi sizes
  REM VDU: PROCftracef("FNpdf_fontsize")
  CASE num% OF
  WHEN 0: =10: REM pica
  WHEN 1: =12: REM elite
  WHEN 2: =17: REM condensed
  WHEN 3: = 6: REM expanded
  ENDCASE
=0

DEF FNpdf_trans(pdf_s$)
  LOCAL pdf_i%,byte%,out$,str$
  REM VDU: PROCftracef("FNpdf_trans")
  IF pdf_s$="" THEN =""
  FOR pdf_i%=1 TO LEN pdf_s$
    byte%=ASC MID$(pdf_s$,pdf_i%,1)
    str$=""
    CASE TRUE OF
      WHEN byte%<32 OR byte%=127
        IF tpub%!CONST_tpub_cc_print=1 THEN str$=FNpdf_display(byte%)
      WHEN byte%>127 AND tpub%!CONST_tpub_cc_print<>0
        IF tpub%!CONST_tpub_cc_print=1 THEN str$=FNpdf_display(byte%)
      WHEN tpub%!CONST_tpub_cc_print<>0
        str$=CHR$ byte%
        tpub%!CONST_tpub_cpos+=1
      OTHERWISE
        tpub%!CONST_tpub_cpos+=1
        IF byte%>127 THEN
          str$=FNpdf_oct(byte%)
        ELSE
          CASE byte% OF
            WHEN ASC"(": str$="\("
            WHEN ASC")": str$="\)"
            WHEN     92: str$="\\"                /* was: WHEN ASC"\": str$="\\"   AMcC: 20-Sep-94 */
            OTHERWISE: str$=CHR$ byte%
          ENDCASE
        ENDIF
    ENDCASE
    out$+=str$
  NEXT
=out$

DEF FNpdf_display(byte%)
  LOCAL buf$
  REM VDU: PROCftracef("FNpdf_display")
  tpub%!CONST_tpub_cpos+=4
  buf$=") SS "+STR$((tpub%!CONST_tpub_style_bits AND &7F)OR 1)+" ("
  REM                                          bold_bit ^
  buf$+="["+RIGHT$("0"+STR$~byte%,2)+"]"
  buf$+=") SS "+STR$(tpub%!CONST_tpub_style_bits AND &7F)+" ("
=buf$

DEF FNpdf_oct(byte%)
  REM VDU: PROCftracef("FNpdf_oct")
=CHR$92+CHR$((byte%>>6 AND 7)+48)+CHR$((byte%>>3 AND 7)+48)+CHR$((byte% AND 7)+48) /* CHR$92: was "\"  AMcC: 20-Sep-94 */

DEF PROCpdf_ensure_dir

  LOCAL f%

  SYS "XOS_File", 8, "PrinterChoices:pdf" TO ; f%
  SYS "XOS_File", 8, "PrinterChoices:pdf.Printers" TO ; f%

ENDPROC

DEF FNpdf_host_desc
LOCAL a%
a%=buff%!24
=a%!CONST_interface_host_desc
