REM > Support - for dot matrix 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:
 *
 * AMcC: 20-Sep-94
 * - Now pre-processed using CPP (cc -E) instead of basic prog 'Constants'.
 *   Allows us to use the same include file "Values" as used by front-end
 *   prog (!Printers.!RunImage).
 * - Uses C-style comments where cc -E  complains about REM ones.
 * - All constants changed from the form CONST_name% to CONST_name.
 * 
 */

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

DEF FNdp_support(buff%)
  LOCAL reason%,psup%,prnt%,prdt%,cnfg%,xbuff%,psize_head%,code_entry%
  REM VDU: PROCftracef("FNdp_support")
  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: PROCdp_m1
    WHEN -2: PROCdp_m2
    WHEN -3: PROCdp_m3
    WHEN -4: PROCdp_m4
    WHEN -5: PROCdp_m5
    WHEN -6: PROCdp_m6
    WHEN -7: PROCdp_m7
    WHEN -8: PROCdp_m8
    WHEN 3: PROCdp_p3
    WHEN 6: PROCdp_p6
    WHEN 8: PROCdp_p8
    WHEN 9: PROCdp_p9
    WHEN 17,18: PROCdp_p17
  ENDCASE
=FALSE

DEF PROCdp_m1
  LOCAL colours%, pdriverdp%, exists%
  REM VDU: PROCftracef("PROCdp_m1")
  REM psup%!CONST_psup_flags OR= 0
  psup%!CONST_psup_type=&FF4
  psup%!CONST_psup_text=%0100
  psup%!CONST_psup_cnfg=CONST_cnfg_dp_MAX/4
  psup%!CONST_psup_vsn=2
  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
  psup%!CONST_psup_rma_block=0
  colours%=FNrmload_latest_module("ColourTrans","System:Modules.Colours")
  IFFNrmload_latest_module("PDriver","Printers:Modules.PDriver")
  IFFNrmload_latest_module("PDumperSupport","Printers:Modules.PDumperSpt")
  pdriverdp%=FNrmload_latest_module("PDriverDP","Printers:Modules.PDriverDP")
  REM ***** WARNING!
  REM ***** THESE VERSION NUMBERS ARE HARD CODED!
  IFpdriverdp%>400 AND colours%<150 THEN
    SYS"Wimp_ReportError",FNmsg_0(FNdp_host_desc,"WA12"), 1 OR 1<<4,FNmsg_1(FNdp_host_desc,"ER2",FNmsg_0(FNdp_host_desc,"ID"))
  ENDIF
/* do not allow this now
  SYS "XOS_ReadVarVal","Printers$DPLJfullQ",,-1,,3 TO,,exists%
  IF exists% THEN DPQ$="F" ELSE DPQ$="S"
*/
DPQ$="S"
ENDPROC

DEF PROCdp_m2
  REM VDU: PROCftracef("PROCdp_m2")
/* REM We don't want to free up the RMA when we quit, thank you very much
 * REM  IF psup%!CONST_psup_rma_block THEN 
 * REM    REM VDU: PROCftracef("*** FREEING R M A ***")
 * REM    SYS "ResourceFS_DeregisterFiles",psup%!CONST_psup_rma_block
 * REM    SYS "OS_Module",7,,psup%!CONST_psup_rma_block: REM OSModule_Free
 * REM    psup%!CONST_psup_rma_block=0
 * REM  ENDIF
 */
ENDPROC

DEF PROCdp_m3
  REM initialise the configuration window
  LOCAL config%,dp_i%,dp_j%
  REM VDU: PROCftracef("PROCdp_m3")
  config%=FNprinter_find_window(prnt%,"configure")
  PROCicon_write(config%,30,FNprinter_read_string(prnt%!CONST_prnt_name))
  PROCicon_write(config%,6,$prnt%!CONST_prnt_type)
  PROCicon_write(config%,3,FNdp_res(cnfg%))
  PROCicon_write(config%,15,FNdp_qual(cnfg%))
  dp_i%=!cnfg%!CONST_cnfg_dp_flags
  IF FNprinter_read_string_entry(prdt%,13)<>"" THEN
    /* Special list of feeds */
    dp_j%=(dp_i% AND &1F80000)>>19
    PROCicon_write(config%,17,FNdp_get_feed_name(FNprinter_read_string_entry(prdt%,13),dp_j%))
  ELSE
    dp_j%=dp_i%>>CONST_dp_flags_feed_offset AND CONST_dp_flags_feed_width
    /* Just the usual Auto/Manual/Roll feeds then. */
    PROCicon_write(config%,17,FNmsg_0(psup%!CONST_psup_msg,"PF"+STR$ dp_j%))
  ENDIF
  IF FNprinter_read_string_entry(prdt%,14)<>"" THEN
    dp_j%=(dp_i% AND &7E000000)>>25
    PROCicon_write(config%,37,FNdp_get_bin_name(FNprinter_read_string_entry(prdt%,14),dp_j%))
    PROCicon_unshade(config%,38)
  ELSE
    PROCicon_write(config%,37,FNmsg_0(psup%!CONST_psup_msg,"OB0"))
    PROCicon_shade(config%,38)
  ENDIF
  IF FNhas_external_config_app(prnt%) THEN
    PROCicon_unshade(config%,35)
  ELSE
    PROCicon_shade(config%,35)
  ENDIF
  IF prnt%!CONST_prnt_flags AND 1<<6 THEN
    PROCicon_shade(config%,8)
    PROCicon_shade(config%,11)
    PROCicon_shade(config%,12)
    PROCicon_shade(config%,14)
    PROCicon_shade(config%,19)
    PROCicon_shade(config%,23)
    PROCicon_shade(config%,24)
  ELSE
    dp_j%=dp_i% AND %000010
    IF dp_j% PROCicon_select(config%,8)ELSE PROCicon_deselect(config%,8)
    dp_j%=dp_i% AND %000100
    IF dp_j% PROCicon_select(config%,11)ELSE PROCicon_deselect(config%,11)
    dp_j%=dp_i% AND %001000
    IF dp_j% PROCicon_select(config%,12)ELSE PROCicon_deselect(config%,12)
    dp_j%=(dp_i% AND %110000)>>4
    PROCicon_write(config%,14,FNmsg_0(psup%!CONST_psup_msg,"TQ"+STR$ dp_j%))
    dp_j%=(dp_i% AND &F00)>>8
    PROCicon_write(config%,23,FNmsg_0(psup%!CONST_psup_msg,"CC"+STR$ dp_j%))
  ENDIF
  dp_i%=prnt%!CONST_prnt_psze
  PROCicon_write(config%,27,$dp_i%!CONST_psze_name)
ENDPROC

DEF PROCdp_m4
  REM create a CNFG block with suitable defaults
  LOCAL dp_s$,dp_nm$,dp_nm2$,dp_i%,dp_s%,dp_t%,dp_co%,dp_ht%,B%,C%,dp_inf%,dp_x%,dp_y%
  REM VDU: PROCftracef("PROCdp_m4")

  REM OSS set the text options to be no highlights, Print linefeeds.
  REM PJC: default changed to be draft with linefeeds.
  cnfg%!CONST_cnfg_dp_flags=FNstore_integer(%011000)
  dp_i%=FNprinter_read_list_integer_entry(prdt%,5,2,1)
  IF dp_i%=0 THEN
    REM no draft - fall back to no highlights
    !cnfg%!CONST_cnfg_dp_flags=%001000
    dp_i%=FNprinter_read_list_integer_entry(prdt%,5,1,1)
  ENDIF
  IF dp_i% THEN
    B%=CONST_ident_POTR
    C%=4
    cnfg%!CONST_cnfg_dp_text=USR(code_entry%+CONST_entry_heap_claim)
    IFcnfg%!CONST_cnfg_dp_text=0 ERROR CONST_error_fatal, FNmsg_0(FNdp_host_desc,"FA5")
    !cnfg%!CONST_cnfg_dp_text=dp_i%
  ELSE
    prnt%!CONST_prnt_flags=prnt%!CONST_prnt_flags OR 1<<6
  ENDIF

  REM try to read the default x and y resolutions and name from the PRDT block
  dp_x%=FNprinter_read_integer_entry(prdt%,8)
  dp_y%=FNprinter_read_integer_entry(prdt%,9)
  dp_nm$=FNprinter_read_string_entry(prdt%,12)
  IF dp_nm$<>"" THEN
    REM try to find the graphics mode which matches this name
    C%=1
    REPEAT
      B%=FNprinter_read_list_integer_entry(prdt%,4,C%,1)
/*      REM first of all, see if we've run out of modes */
      IF B%=0 THEN
        C%=-1
      ELSE
        dp_nm2$=FNprinter_read_string_entry(B%,8)
        REM if no match, try the next mode
        IFdp_nm$<>dp_nm2$ C%+=1
      ENDIF
    UNTIL C%=-1 OR dp_nm$=dp_nm2$
    REM if we found it, remember where it was
    IF C%<>-1 dp_i%=C%
  ELSE
    IF (dp_x%<>0 AND dp_y%<>0) THEN
      REM try to find the graphics mode which matches this resolution
      C%=1
      REPEAT
        B%=FNprinter_read_list_integer_entry(prdt%,4,C%,1)
  /*      REM first of all, see if we've run out of modes */
        IF B%=0 THEN
          C%=-1
        ELSE
          dp_s%=FNprinter_read_integer_entry(B%,4)
          dp_t%=FNprinter_read_integer_entry(B%,5)
          REM if no match, try the next mode
          IFdp_s%<>dp_x% OR dp_t%<>dp_y% C%+=1
        ENDIF
      UNTIL C%=-1 OR (dp_s%=dp_x% AND dp_t%=dp_y%)
      REM if we found it, remember where it was
      IF C%<>-1 dp_i%=C%
    ELSE
      REM show we didn't match - which we couldn't 'cos we didn't have the values
      C%=-1
    ENDIF
  ENDIF

/*  REM if didn't match on supplied resolutions, or no resolutions given
 *  REM do a best fit
 */
  IF C%=-1 THEN
    REM OSS set the graphics options to be the highest non-interlaced resolution
    B%=CONST_ident_PDBF
    C%=256
    dp_inf%=USR(code_entry%+CONST_entry_heap_claim)
    IFdp_inf%=0 ERROR CONST_error_fatal, FNmsg_0(FNdp_host_desc,"FA5")
    C%=1
    dp_i%=FALSE
    REPEAT
      B%=FNprinter_read_list_integer_entry(prdt%,4,C%,1)
      IF B%=0 THEN
        REM run out of parameters, go back to the last one
        C%-=1
        dp_i%=TRUE
      ELSE
        $dp_inf%=FNprinter_read_string_entry(B%,6)
        IF dp_inf%?CONST_dp_y_interlace=0 AND dp_inf%?CONST_dp_x_interlace=0 THEN
          C%+=1
        ELSE
          C%-=1
          dp_i%=TRUE
        ENDIF
      ENDIF
    UNTIL dp_i%
    dp_i%=C%
    B%=CONST_ident_PDBF
    C%=dp_inf%
    CALL code_entry%+CONST_entry_heap_free
  ENDIF

  B%=CONST_ident_POTR
  C%=4
  cnfg%!CONST_cnfg_dp_graphics=USR(code_entry%+CONST_entry_heap_claim)
  IFcnfg%!CONST_cnfg_dp_graphics=0 ERROR CONST_error_fatal, FNmsg_0(FNdp_host_desc,"FA5")
  !cnfg%!CONST_cnfg_dp_graphics=FNprinter_read_list_integer_entry(prdt%,4,dp_i%,1)

  REM ensure that the module is present in memory
  dp_s$=FNprinter_read_string_entry(FNprinter_read_integer_entry(!cnfg%!CONST_cnfg_dp_graphics,1),2)
  IFFNrmload_latest_module(dp_s$,"Printers:PDumpers."+dp_s$)

  REM ensure that the palette file needed at the resolution is cached
  REM bit 23 of palette no. flags whether already ensured or not
  dp_s$=STR$(FNprinter_read_integer_entry(!cnfg%!CONST_cnfg_dp_graphics,2) AND &7FFFFF)
  PROCdp_ensure_resource_file("Resources.Printers.Palettes."+dp_s$,"Printers:Palettes."+dp_s$,!cnfg%!CONST_cnfg_dp_graphics)

  REM initialise the quality
  REM see if a quality was provided in the PDF
  dp_i%=FNprinter_read_integer_entry(prdt%,10)
  REM get the qualities available at the configured resolution
  dp_s%=FNdp_get_quality_options(!cnfg%!CONST_cnfg_dp_graphics)
  IF dp_i%<>0 THEN
/*
 *   REM validate values! reset dp_i% to zero if the requested
 *   REM colour and halftone type aren't available at the specified
 *   REM resolution
 *   REM
 *   REM Note that the 'new' strip types (3,4 and 5) cannot be set from
 *   REM the printer definition file, therefore aren't checked for here
 */
    dp_co%=dp_i% AND &FF
    dp_ht%=(dp_i% AND &FF00)>>8
    CASE dp_co% OF
      WHEN 0: REM mono
        IF (dp_s% AND 7) THEN
          IF dp_ht%=4 AND (dp_s% AND 1)=0 dp_i%=0
          IF dp_ht%=8 AND (dp_s% AND 2)=0 dp_i%=0
          IF dp_ht%=1 AND (dp_s% AND 4)=0 dp_i%=0
        ELSE
          dp_i%=0
        ENDIF
      WHEN 1: REM greyscale
        IF (dp_s% AND &70) THEN
          IF dp_ht%=4 AND ((dp_s%>>4) AND 1)=0 dp_i%=0
          IF dp_ht%=8 AND ((dp_s%>>4) AND 2)=0 dp_i%=0
          IF dp_ht%=1 AND ((dp_s%>>4) AND 4)=0 dp_i%=0
        ELSE
          dp_i%=0
        ENDIF
      WHEN 2: REM colour
        IF (dp_s% AND &700) THEN
          IF dp_ht%=4 AND ((dp_s%>>8) AND 1)=0 dp_i%=0
          IF dp_ht%=8 AND ((dp_s%>>8) AND 2)=0 dp_i%=0
          IF dp_ht%=1 AND ((dp_s%>>8) AND 4)=0 dp_i%=0
        ELSE
          dp_i%=0
        ENDIF
    ENDCASE
  ENDIF
  IF dp_i%<>0 THEN
    cnfg%!CONST_cnfg_dp_options=FNstore_integer(dp_i%)
  ELSE
    PROCdp_decode_options(dp_s%,dp_co%,dp_ht%)
    cnfg%!CONST_cnfg_dp_options=FNstore_integer(dp_ht%<<8 OR dp_co%)
  ENDIF

  $buff%=FNprinter_read_string_entry(prdt%,2)
  B%=buff%
  C%=2
  prnt%!CONST_prnt_name=USR(code_entry%+CONST_entry_store_string)
  dp_s$=FNprinter_read_string_entry(prdt%,3)
/*  REM if the sprite name isn't the same as the class name, store the new sprite name */
  IF dp_s$<>"dp" $buff%=dp_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 ...
  REM start by trying to read the 'default_paper_size' entry
  REM from the PRDT block (entry 7)
  dp_s$=FNprinter_read_string_entry(prdt%,7)
  REM fall back to going for the default
  IF dp_s$="" dp_s$=FNmsg_0(psup%!CONST_psup_msg,"PAP")

  dp_i%=0
  dp_t%=psize_head%
  WHILE dp_t%<>0 AND dp_i%=0
    IF dp_s$=FNprinter_read_string(dp_t%!CONST_psze_name) THEN dp_i%=dp_t%
    dp_t%=dp_t%!CONST_psze_next
  ENDWHILE
  /* if we run out of paper entries, DON'T just go for the first one */
  /* Find the paper size with the maximal matching prefix length */
  IF dp_i%=0 THEN
    dp_t%=psize_head%
    dp_s%=0
    WHILE dp_t%<>0
      dp_nm2$=FNprinter_read_string(dp_t%!CONST_psze_name)
      WHILE dp_s%<LENdp_nm2$ AND LEFT$(dp_nm2$,dp_s%+1)=LEFT$(dp_s$,dp_s%+1)
        dp_s%+=1
        dp_i%=dp_t%
      ENDWHILE
      dp_t%=dp_t%!CONST_psze_next
    ENDWHILE
    PROCerror_warning(FNmsg_3(FNdp_host_desc,"WA11",dp_s$,FNprinter_read_string(dp_i%!CONST_psze_name),$prnt%!CONST_prnt_name))
  ENDIF
  prnt%!CONST_prnt_psze=dp_i%

  REM if this printer supports fast parallel, set the appropriate flag
  dp_i%=FNprinter_read_integer_entry(prdt%,11)
  IFdp_i%<>0 prnt%!CONST_prnt_flags = prnt%!CONST_prnt_flags OR (1<<7)
ENDPROC

DEF PROCdp_ensure_resource_file(resource$,disc$,gprdt%)
  LOCAL obj_type%,load_addr%,exec_addr%,file_size%,obj_attr%,rma_size%,rma_block%
  LOCAL found_type%,found_load%,found_exec%,found_size%,c%,a%,w%,pnum%,reload_if_outofdate%
  REM VDU: PROCftracef("dp_ensure_resource_file")
  REM We use this to load palette files for the printers in order to reduce
  REM the probability of having to ask for the printers disc again later.

  REM check for out of date palette if we have not ensured this one before (bit 23 of palette number)
  pnum% = FNprinter_read_integer_entry(gprdt%,2)
  reload_if_outofdate% = ((pnum% AND &800000) = 0)
  PROCprinter_write_integer_entry(gprdt%,2,pnum% OR &800000):REM we (will) have ensured it

  REM First of all, check if the file exists already
  SYS "OS_File",17,"Resources:"+resource$ TO found_type%,,found_load%,found_exec%,found_size%: REM OS_FileReadNoPath
  
  IF found_type% AND reload_if_outofdate%=FALSE THEN ENDPROC

  SYS "OS_File",17,disc$ TO obj_type%,,load_addr%,exec_addr%,file_size%,obj_attr%: REM OS_FileReadNoPath
  IF obj_type%<>1 SYS "OS_File",19,disc$,obj_type%: REM OS_FileMakeError

  IF found_type% THEN
    IFfound_load%=load_addr% AND found_exec%=exec_addr% AND found_size%=file_size% ENDPROC
    REM cached palette is not the same as the one on disc
    REM try to remove the cached palette
    c%=OPENIN("Resources:"+resource$)
    IFc%=0 ERROR CONST_error_ok, FNmsg_1(FNdp_host_desc,"OKBB",resource$)
    SYS"OS_FSControl",21,c% TO ,a%,w%
    CLOSE#c%
    IF(w%AND&FF)<>46 ERROR CONST_error_ok, FNmsg_1(FNdp_host_desc,"OKBC",resource$)
    a%-=(LENresource$+4ANDNOT3)+4
    a%-=20
    IFa%!-4 = &48434143 THEN
      SYS"ResourceFS_DeregisterFiles",a%
      SYS"OS_Module",7,,a%-4
    ENDIF
  ENDIF

  rma_size%=20+(LEN resource$+4 AND NOT 3)+4+(file_size%+3 AND NOT 3): REM Size needed for this file only
  REM VDU: PROCftracef("File "+disc$+", size "+STR$ file_size%)

  REM claim some RMA for the file
  SYS "OS_Module",6,,,rma_size%+8 TO,,rma_block%: REM OSModule_Alloc
  REM Put a check tag at the beginning of the block
  !rma_block%=&48434143:REM CACH
  rma_block%+=4
/*  REM Fill in the block */
  rma_block%!0=rma_size%
  rma_block%!4=load_addr%
  rma_block%!8=exec_addr%
  rma_block%!12=file_size%
  rma_block%!16=obj_attr%
  $(rma_block%+20)=resource$
  rma_block%!(20+LEN resource$)=0 /* : REM pad with 0's */
  rma_block%!(20+(LEN resource$+4 AND NOT 3))=file_size%+4
  SYS "OS_File",16,disc$,rma_block%+20+(LEN resource$+4 AND NOT 3)+4: REM OS_FileLoadNoPath
  rma_block%!rma_size%=0: REM Terminator
  SYS "ResourceFS_RegisterFiles",rma_block%
ENDPROC

DEF PROCdp_m5
  REM cache any palette files that are used by dp printers and ensure
  REM that the relevant PDumper modules are loaded
  LOCAL dp_prnt%,dp_cnfg%,dp_graphics_prdt%,dp_pal$
  REM VDU: PROCftracef("PROCdp_m5")
  dp_prnt%=prnt%
  WHILE dp_prnt%>0
    IF dp_prnt%!CONST_prnt_psup=psup% THEN
      REM got a printer in our class - cache the palette file
      dp_cnfg%=dp_prnt%!CONST_prnt_cnfg
      dp_graphics_prdt%=!dp_cnfg%!CONST_cnfg_dp_graphics
      REM bit 23 of palette no. flags whether already ensured or not
      dp_pal$=STR$(FNprinter_read_integer_entry(dp_graphics_prdt%,2) AND &7FFFFF)
      PROCdp_ensure_resource_file("Resources.Printers.Palettes."+dp_pal$,"Printers:Palettes."+dp_pal$,dp_graphics_prdt%)

      REM and ensure the pdumper module
      dp_pal$=FNprinter_read_string_entry(FNprinter_read_integer_entry(dp_graphics_prdt%,1),2)
      IFFNrmload_latest_module(dp_pal$, "Printers:PDumpers."+dp_pal$)
    ENDIF
    dp_prnt%=dp_prnt%!CONST_prnt_next
  ENDWHILE
ENDPROC

DEF PROCdp_m6
  REM do whatever is necessary to prime the specified printer
  LOCAL dp_s$,dp_t$,dp_i%,xres%,yres%,halftone%,ptr%,flags%,pal%,dmp$,inf%,strip%,graphics_prdt%,text_prdt%,B%,C%
  LOCAL flags%,newblock%,i%,a$,s%
  REM VDU: PROCftracef("PROCdp_m6")
  REM 7 is the magic number for the dumper driver
  SYS "XPDriver_SelectDriver",7
  dp_s$=FNprinter_read_string(prnt%!CONST_prnt_name)
  IF dp_s$="" THEN
    dp_s$=$prnt%!CONST_prnt_type
    IF LEN dp_s$>20 THEN
      dp_i%=LEN dp_s$
      WHILE MID$(dp_s$,dp_i%,1)<>" " AND dp_i%>0
        dp_i%-=1
      ENDWHILE
      IF dp_i% dp_s$=LEFT$(dp_s$,dp_i%-1)ELSE dp_s$=LEFT$(dp_s$,20)
    ENDIF
  ENDIF
  graphics_prdt%=!cnfg%!CONST_cnfg_dp_graphics
  xres%=FNprinter_read_integer_entry(graphics_prdt%,4)
  yres%=FNprinter_read_integer_entry(graphics_prdt%,5)
  halftone%=(!cnfg%!CONST_cnfg_dp_options AND &FF00)>>8
  strip%=!cnfg%!CONST_cnfg_dp_options AND &FF
  REM WARNING!
  REM The comparison is made against strip type 2 (colour) or greater
  REM This assumes, therefore, that any strip types that are 2 or greater
  REM are colour which is currently true
  IF (strip% >= 2) THEN
   SYS"XPDriver_SetInfo",,xres%,yres%,1,dp_s$,xres%/halftone%,yres%/halftone% TO ptr%;dp_i%
  ELSE
   SYS"XPDriver_SetInfo",,xres%,yres%,0,dp_s$,xres%/halftone%,yres%/halftone% TO ptr%;dp_i%
  ENDIF
  IF (dp_i% AND 1) AND (ptr%<>0) THEN
    dp_s$="": ptr%+=4
    WHILE ?ptr%: dp_s$+=CHR$ ?ptr%: ptr%+=1: ENDWHILE
    ERROR CONST_error_ok,dp_s$
    ENDPROC
  ENDIF

  REM bit 23 of palette no. flags whether already ensured or not
  dp_s$=STR$(FNprinter_read_integer_entry(graphics_prdt%,2) AND &7FFFFF)
  B%=CONST_ident_PDBF
  C%=256
  pal%=USR(code_entry%+CONST_entry_heap_claim)
  IFpal%=0 ERROR CONST_error_fatal, FNmsg_0(FNdp_host_desc,"FA5")
  $pal%="Resources:$.Resources.Printers.Palettes."+dp_s$
  inf%=USR(code_entry%+CONST_entry_heap_claim)
  IFinf%=0 ERROR CONST_error_fatal, FNmsg_0(FNdp_host_desc,"FA5")
  $inf%=FNprinter_read_string_entry(graphics_prdt%,6)
  strip%=!cnfg%!CONST_cnfg_dp_options AND &FF
/*  REM if we have strip type 5 and the dumper doesn't support it,
 *  REM deprecate it down to strip type 3
 */
  IF strip%=5 THEN
   dp_i%=FNprinter_read_integer_entry(graphics_prdt%,1)
   dp_i%=FNprinter_read_integer_entry(dp_i%,1)
/*   REM we've selected the dumper driver, so this should work :-) */
   SYS"XPDriver_MiscOp",&80000002,dp_i% TO ptr%;dp_i%
   IF(dp_i%AND1)=0 IFptr%<>&80000002 IF(ptr% AND (1<<5))=0 strip%=3
  ENDIF
/*  REM this may be necessary, if multiple palettes for one printer */
  PROCdp_ensure_resource_file("Resources.Printers.Palettes."+dp_s$,"Printers:Palettes."+dp_s$,graphics_prdt%)

  REM Module name:
  dp_s$=FNprinter_read_string_entry(FNprinter_read_integer_entry(graphics_prdt%,1),2)
  dmp$="RMLoad Printers:PDumpers."+dp_s$+CHR$ 13

  REM set passes per line entry
  REM WARNING!
  REM The comparison is made against strip type 2 (colour) or greater
  REM This assumes, therefore, that any strip types that are 2 or greater
  REM are colour which is currently true
  IF strip%>=2 inf%?CONST_dp_pass_per_line=4 ELSE inf%?CONST_dp_pass_per_line=1

  REM set strip type field
  inf%?CONST_dp_strip_type=strip%

  REM set output bpp field
  IF strip%=0 inf%?CONST_dp_output_bpp=1 ELSE inf%?CONST_dp_output_bpp=8

  REM set num passes field
  IF strip%=3 inf%?CONST_dp_no_passes=3 ELSE inf%?CONST_dp_no_passes=1

  REM OSS Set the NoPageAdvance bit in the flags if paper feed is "Roll"
  flags%=FNprinter_read_integer_entry(graphics_prdt%,7)
  IF(!cnfg%!CONST_cnfg_dp_flags>>CONST_dp_flags_feed_offset AND CONST_dp_flags_feed_width)=CONST_dp_flags_feed_roll flags%+=2

  REM OSS Fixup old version numbers by moving it to the new location.
  IF(flags%>>>24)=0 flags%=flags% OR inf%?CONST_dp_data_old_version<<24

  REM OSS Set lines per page if version>0. We only need to check the new
  REM version field as the fixup has already been done.
  IF(flags%>>>24)>0 THEN
    dp_i%=prnt%!CONST_prnt_psze
    inf%?CONST_dp_data_num_lines=dp_i%!CONST_psze_theight
  ENDIF

  flags%=FNprinter_read_integer_entry(graphics_prdt%,7)
  IF ((flags% >>> 24) < 5) THEN
    SYS "XPDriver_SetDriver",,FNprinter_read_integer_entry(FNprinter_read_integer_entry(graphics_prdt%,1),1),dmp$,pal%,inf%,flags%
  ELSE
    s%=4*(20+2)
    FOR B%=0 TO 19
      s%+=1+LENFNprinter_read_string_entry(graphics_prdt%,10+B%)
    NEXT
    C%=s%
    B%=CONST_ident_DATA
    newblock%=USR(code_entry%+CONST_entry_heap_claim)
    IFnewblock%=0 ERROR CONST_error_fatal, FNmsg_0(FNdp_host_desc,"FA5")
    !newblock%=20
    newblock%!4=s%
    C%=newblock%+4*(20+2)
    FOR B%=0 TO 19
      newblock%!(8+4*B%)=C%-newblock%
      a$=FNprinter_read_string_entry(graphics_prdt%,10+B%)
      ?C%=LENa$:C%+=1
      IF LEN a$>0 THEN
        FOR i%=1 TO LEN a$
         ?C%=ASC(MID$(a$,i%,1))
         C%+=1
        NEXT
      ENDIF
    NEXT
    SYS "XPDriver_SetDriver",,FNprinter_read_integer_entry(FNprinter_read_integer_entry(graphics_prdt%,1),1),dmp$,pal%,inf%,flags%,newblock%
    B%=CONST_ident_DATA
    C%=newblock%
    CALL code_entry%+CONST_entry_heap_free
  ENDIF
  B%=CONST_ident_PDBF
  C%=pal%
  CALL code_entry%+CONST_entry_heap_free
  C%=inf%
  CALL code_entry%+CONST_entry_heap_free
  SYS "OS_CLI","Unset PDriver$TextChars1"

  REM point to the chars PRDT block
  dp_i%=FNprinter_read_integer_entry(prdt%,6)
  IF dp_i% THEN
    dp_i%=dp_i%!CONST_prdt_1st
    WHILE dp_i%
      IF dp_i%?CONST_char_char=ASC"" THEN
        dp_s$=FNdp_hex2(ASC "")+FNdp_hex2(dp_i%?CONST_char_len)
        ptr%=dp_i%+CONST_char_trans: dp_i%=dp_i%?CONST_char_len
        WHILE dp_i%
          dp_s$+=FNdp_hex2(?ptr%)
          ptr%+=1
          dp_i%-=1
        ENDWHILE
        SYS"OS_CLI","Set PDriver$TextChars1 "+dp_s$
      ELSE
        dp_i%=dp_i%!CONST_char_next
      ENDIF
    ENDWHILE
  ENDIF

  IF cnfg%!CONST_cnfg_dp_text=0 THEN
    SYS"OS_CLI","Unset PDriver$TextPage"
  ELSE
    text_prdt%=!cnfg%!CONST_cnfg_dp_text
    dp_i%=prnt%!CONST_prnt_psze
    dp_s$="-Ph "+STR$ dp_i%!CONST_psze_theight+" -Mt "+STR$ dp_i%!CONST_psze_ttop+" -Mb "
    dp_s$+=STR$ dp_i%!CONST_psze_tbottom+" -Ml "+STR$ dp_i%!CONST_psze_tleft+" -Th "
    IF cnfg%!CONST_cnfg_dp_flags AND 2 dp_s$+="2" ELSE dp_s$+="0"
    dp_s$+=" -Nl "
    IF cnfg%!CONST_cnfg_dp_flags AND 8 THEN
      dp_s$+=FNungstrans(FNungstrans(FNprinter_read_string_entry(text_prdt%,6)))
    ELSE
      dp_s$+=FNungstrans(FNungstrans(FNprinter_read_string_entry(text_prdt%,5)))
    ENDIF
    dp_t$=FNprinter_read_string_entry(text_prdt%,7)
    IF dp_t$<>"" dp_s$+=" -Rs "+FNungstrans(FNungstrans(dp_t$))
    dp_t$=FNprinter_read_string_entry(text_prdt%,11)
    IF dp_t$<>"" dp_s$+=" -Cd "+FNungstrans(FNungstrans(dp_t$))
    SYS"OS_CLI","Set PDriver$TextPage "+dp_s$
  ENDIF
ENDPROC

DEF PROCdp_m7
  LOCAL queu%,dp_p%,B%,C%
  REM VDU: PROCftracef("PROCdp_m7")
  queu%=!xbuff%
  dp_p%=queu%!CONST_queu_tprv
  IF dp_p% THEN
    PROCfree_structure(dp_p%!CONST_tprv_dp_page_prologue)
    B%=CONST_ident_TPRV
    C%=dp_p%
    CALL code_entry%+CONST_entry_heap_free
    queu%!CONST_queu_tprv=0
  ENDIF
ENDPROC

DEF PROCdp_p3
  REM VDU: PROCftracef("PROCdp_p3")
  SYS"Wimp_CloseWindow",,xbuff%
ENDPROC

DEF PROCdp_p6
  LOCAL wind%,dummy%
  REM VDU: PROCftracef("PROCdp_p6")
  REM mouseclick on the configure window
  CASE xbuff%!8 OF
    WHEN 2: REM menu
      CASE xbuff%!16 OF
        WHEN 20: PROCdp_menu("ME1",TRUE,TRUE)
        WHEN 18: PROCdp_menu("ME2",TRUE,TRUE)
        WHEN  4: PROCdp_menu("ME3",TRUE,TRUE)
        WHEN 19: PROCdp_menu("ME4",TRUE,TRUE)
        WHEN 24: PROCdp_menu("ME5",TRUE,TRUE)
        WHEN 26: PROCdp_menu("MP1",TRUE,TRUE)
        WHEN 38: PROCdp_menu("ME6",TRUE,TRUE)
      ENDCASE
    WHEN 4: REM select
      CASE xbuff%!16 OF
        WHEN 25
          wind%=xbuff%!12
          PROCdp_save_configuration(wind%)
          !xbuff%=wind%:SYS"Wimp_CloseWindow",,xbuff%
        WHEN 20
          PROCdp_menu("ME1",TRUE,TRUE)
        WHEN 18
          PROCdp_menu("ME2",TRUE,TRUE)
        WHEN  4
          PROCdp_menu("ME3",TRUE,TRUE)
        WHEN 19
          PROCdp_menu("ME4",TRUE,TRUE)
        WHEN 24
          PROCdp_menu("ME5",TRUE,TRUE)
        WHEN 26
          PROCdp_menu("MP1",TRUE,TRUE)
        WHEN 38
          PROCdp_menu("ME6",TRUE,TRUE)
        WHEN 31
          !xbuff%=xbuff%!12
          SYS"Wimp_CloseWindow",,xbuff%
        WHEN 35
          dummy%=FNexternal_config_app(prnt%)
      ENDCASE
    WHEN 1: REM adjust
      CASE xbuff%!16 OF
        WHEN 25
          wind%=xbuff%!12
          PROCdp_save_configuration(wind%)
        WHEN 35
          dummy%=FNexternal_config_app(prnt%)
      ENDCASE
  ENDCASE
ENDPROC

DEF PROCdp_p8
  REM a key press!
  LOCAL dp_i%
  REM VDU: PROCftracef("PROCdp_p8")
  dp_i%=psup%!CONST_psup_wind
  WHILE dp_i%
    IF dp_i%!CONST_wind_hand=!xbuff% THEN
      IF xbuff%!24=13 THEN
        CASE $(dp_i%+CONST_wind_name)OF
          WHEN "configure"
            SYS "Wimp_CloseWindow",,xbuff%
            PROCdp_save_configuration(!xbuff%)
        ENDCASE
      ELSE
        SYS "Wimp_ProcessKey",xbuff%!24
      ENDIF

      ENDPROC
    ENDIF

    dp_i%=dp_i%!CONST_wind_next
  ENDWHILE
ENDPROC

DEF PROCdp_p9
  LOCAL adjust%,wind%,icon%,ptr%,xres%,yres%,dp_s$,dp_i%,dp_j%,dp_k%
  REM VDU: PROCftracef("PROCdp_p9")
/*
 * 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.
 */
  wind%=FNprinter_find_window(prnt%,"configure")
  adjust%=FNwas_adjust_used
  CASE dp_menu_chsn$ OF
    WHEN "ME1": icon%=3
    WHEN "ME2": icon%=17
    WHEN "ME3": icon%=15
    WHEN "ME4": icon%=14
    WHEN "ME5": icon%=23
    WHEN "MP1": icon%=27
    WHEN "ME6": icon%=37
  ENDCASE
  ptr%=dp_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 dp_menu_chsn$="ME1" THEN
    REM if the resolution changes, we may have to change the quality as well
    dp_j%=prdt%!20
    dp_s$=FNicon_read(wind%,3)
    WHILE dp_j%
      dp_k%=!dp_j%!CONST_lstd_1st
      IF (dp_s$=FNmsg_2(psup%!CONST_psup_msg,"RES",STR$ !dp_k%!20,STR$ !dp_k%!24)) OR \
         (dp_s$=$(dp_k%!36)) THEN
/*
 *       REM ok - found the pointer to the graphics data, now check the graphics quality
 *       REM basically, we need to see if the request quality is available in this dump
 *       REM if it isn't, we reset it to the best fit we can manage
 */
        dp_s$=FNicon_read(wind%,15): dp_i%=INSTR(dp_s$,",")
        CASE LEFT$(dp_s$,dp_i%-1)OF
          WHEN FNmsg_0(psup%!CONST_psup_msg,"CO1"):  dp_j%=1
          WHEN FNmsg_0(psup%!CONST_psup_msg,"CO1s"): dp_j%=1
          WHEN FNmsg_0(psup%!CONST_psup_msg,"CO2"):  dp_j%=2
          WHEN FNmsg_0(psup%!CONST_psup_msg,"CO4"):  dp_j%=4
          WHEN FNmsg_0(psup%!CONST_psup_msg,"CO5"):  dp_j%=5
          WHEN FNmsg_0(psup%!CONST_psup_msg,"CO5s"): dp_j%=5
          OTHERWISE:                                 dp_j%=0
        ENDCASE
        dp_s$=MID$(dp_s$,dp_i%+2)
        CASE dp_s$ OF
          WHEN FNmsg_0(psup%!CONST_psup_msg,"HT8"):  dp_i%=8
          WHEN FNmsg_0(psup%!CONST_psup_msg,"HT8s"): dp_i%=8
          WHEN FNmsg_0(psup%!CONST_psup_msg,"HT1"):  dp_i%=1
          WHEN FNmsg_0(psup%!CONST_psup_msg,"HT1s"): dp_i%=1
          OTHERWISE:                                 dp_i%=4
        ENDCASE
        dp_k%=FNdp_get_quality_options(dp_k%)
        IF(dp_k% AND (7<<(dp_j%*4)))=0 dp_j%=-1
        IF dp_j%<>-1 THEN
          dp_j%=dp_k%>>(dp_j%*4)
          CASE dp_i% OF
            WHEN 4: IF(dp_j% AND 1)=0 dp_i%=-1
            WHEN 8: IF(dp_j% AND 2)=0 dp_i%=-1
            WHEN 1: IF(dp_j% AND 4)=0 dp_i%=-1
          ENDCASE
        ENDIF
        IF dp_j%=-1 OR dp_i%=-1 THEN
          PROCdp_decode_options(dp_k%,dp_j%,dp_i%)
          PROCicon_write(wind%,15,FNdp_qual_name(dp_j% + (dp_i% << 8)))
        ENDIF
        dp_j%=0
      ELSE
        dp_j%=!dp_j%
      ENDIF
    ENDWHILE
  ENDIF
  IF adjust% THEN
    SYS"Wimp_GetPointerInfo",,xbuff%
    PROCdp_menu(dp_menu_chsn$,FALSE,FALSE)
  ENDIF
ENDPROC

DEF PROCdp_p17
  LOCAL wind%,dp_s$,dp_t$
  REM VDU: PROCftracef("PROCdp_p17")
  CASE xbuff%!16 OF
    WHEN &502: REM HelpRequest
      wind%=psup%!CONST_psup_wind
      WHILE wind%
        IF wind%!CONST_wind_hand=xbuff%!32 THEN
          CASE $(wind%+CONST_wind_name)OF
            WHEN "configure"
              dp_s$=STR$ xbuff%!36
              CASE xbuff%!36 OF
                WHEN 8,11,12: IF FNicon_set(xbuff%!32,xbuff%!36)dp_s$+="b" ELSE dp_s$+="a"
              ENDCASE
              dp_t$=FNmsg_0(psup%!CONST_psup_msg,"CON"+dp_s$)
              IFdp_t$="CON"+dp_s$ dp_t$=FNmsg_0(psup%!CONST_psup_msg,"CON")
              PROCinteractive_help(dp_t$)
          ENDCASE
          wind%=0
        ELSE
          wind%=wind%!CONST_wind_next
          IF wind%=0 PROCinteractive_help(FNmsg_0(psup%!CONST_psup_msg,"H"+dp_menu_chsn$))
        ENDIF
      ENDWHILE
    WHEN &8014B
      /*PrintInterrogate*/
      CASE xbuff%!20 OF
      WHEN 0
        IF prnt% AND xbuff%!24=prnt% THEN PROCdp_interrogate0
      ENDCASE
  ENDCASE
ENDPROC

DEF PROCdp_interrogate0
  LOCAL a$,sender%
  /* Ack the message */
  xbuff%!12=xbuff%!8
  sender%=xbuff%!4
  SYS "Wimp_SendMessage",19,xbuff%,sender%
  /* Construct and send the reply */
  xbuff%!28=FNprinter_read_integer_entry(!cnfg%!CONST_cnfg_dp_graphics,2)
  xbuff%!32=FNprinter_read_integer_entry(!cnfg%!CONST_cnfg_dp_graphics,3)
  xbuff%!36=FNprinter_read_integer_entry(!cnfg%!CONST_cnfg_dp_graphics,4)
  xbuff%!40=FNprinter_read_integer_entry(!cnfg%!CONST_cnfg_dp_graphics,5)
  xbuff%!44=FNprinter_read_integer_entry(!cnfg%!CONST_cnfg_dp_graphics,7)
  a$=FNprinter_read_string_entry(!cnfg%!CONST_cnfg_dp_graphics,8)+CHR$(0)
  $(xbuff%+48)=a$
  !xbuff%=(48+3+LENa$)ANDNOT3
  SYS "Wimp_SendMessage",17,xbuff%,sender%
ENDPROC

DEF PROCdp_save_configuration(window%)
  LOCAL dp_i%,dp_j%,dp_k%,dp_s$,B%,C%
  REM VDU: PROCftracef("PROCdp_save_configuration")
  prdt%=FNprinter_find_prdata_entry(psup%,FNicon_read(window%,6))
  PROCfree_structure(prnt%!CONST_prnt_name)
  $buff%=FNicon_read(window%,30)
  B%=buff%
  C%=2
  prnt%!CONST_prnt_name=USR(code_entry%+CONST_entry_store_string)
  dp_i%=cnfg%
  FOR dp_j%=1 TO CONST_cnfg_dp_MAX/4
    PROCfree_structure(!dp_i%)
   !dp_i%=0: dp_i%+=4
  NEXT

  dp_j%=0
  IF FNprinter_read_string_entry(prdt%,13)="" THEN
    IF FNicon_read(window%,17)=FNmsg_0(psup%!CONST_psup_msg,"PF1")dp_j%+=CONST_dp_flags_feed_manual<<CONST_dp_flags_feed_offset
    IF FNicon_read(window%,17)=FNmsg_0(psup%!CONST_psup_msg,"PF2")dp_j%+=CONST_dp_flags_feed_roll<<CONST_dp_flags_feed_offset
  ELSE
    dp_n%=FNdp_binfeed_save("Feeds",FNprinter_read_string_entry(prdt%,13),FNicon_read(window%,17))
    dp_j%=dp_n%<<19
  ENDIF
  IF FNprinter_read_string_entry(prdt%,14)<>"" THEN
    dp_n%=FNdp_binfeed_save("Bins",FNprinter_read_string_entry(prdt%,14),FNicon_read(window%,37))
    dp_j%+=dp_n%<<25
  ENDIF
  IF FNicon_set(window%,8)dp_j%+=2
  IF FNicon_set(window%,11)dp_j%+=4
  IF FNicon_set(window%,12)dp_j%+=8
  CASE FNicon_read(window%,14)OF
    WHEN FNmsg_0(psup%!CONST_psup_msg,"TQ1"): dp_j%+=1<<4: dp_i%=2
    WHEN FNmsg_0(psup%!CONST_psup_msg,"TQ2"): dp_j%+=1<<5: dp_i%=3
    OTHERWISE: dp_i%=1
  ENDCASE
  CASE FNicon_read(window%,23)OF
    WHEN FNmsg_0(psup%!CONST_psup_msg,"CC1"): dp_j%+=1<<8
    WHEN FNmsg_0(psup%!CONST_psup_msg,"CC2"): dp_j%+=1<<9
  ENDCASE
  cnfg%!CONST_cnfg_dp_flags=FNstore_integer(dp_j%)

  dp_j%=FNprinter_read_list_integer_entry(prdt%,5,dp_i%,1)
  IF dp_j% THEN
    B%=CONST_ident_POTR
    C%=4
    cnfg%!CONST_cnfg_dp_text=USR(code_entry%+CONST_entry_heap_claim)
    IFcnfg%!CONST_cnfg_dp_text=0 ERROR CONST_error_fatal, FNmsg_0(FNdp_host_desc,"FA5")
    !cnfg%!CONST_cnfg_dp_text=dp_j%
    prnt%!CONST_prnt_flags=prnt%!CONST_prnt_flags AND NOT(1<<6)
  ELSE
    prnt%!CONST_prnt_flags=prnt%!CONST_prnt_flags OR 1<<6
  ENDIF

  REM point to the resolution possibilities
  dp_j%=prdt%!20: REM printer name is 8, short name is 12, sprite name is 16, resolution is 20
  dp_s$=FNicon_read(window%,3)
  WHILE dp_j%
    dp_k%=!dp_j%!CONST_lstd_1st: REM get the pointer
    REM module is 8, palette is 12, options is 16, pxres is 20, pyres is 24
    IF (dp_s$=FNmsg_2(psup%!CONST_psup_msg,"RES",STR$ !dp_k%!20,STR$ !dp_k%!24)) OR \
       (dp_s$=$(dp_k%!36)) THEN
      dp_j%=0
    ELSE
      dp_j%=!dp_j%
    ENDIF
  ENDWHILE
  B%=CONST_ident_POTR:C%=4
  cnfg%!CONST_cnfg_dp_graphics=USR(code_entry%+CONST_entry_heap_claim)
  IFcnfg%!CONST_cnfg_dp_graphics=0 ERROR CONST_error_fatal, FNmsg_0(FNdp_host_desc,"FA5")
  !cnfg%!CONST_cnfg_dp_graphics=dp_k%

  dp_s$=FNicon_read(window%,15)
  dp_i%=INSTR(dp_s$,",")
  CASE LEFT$(dp_s$,dp_i%-1)OF
    WHEN FNmsg_0(psup%!CONST_psup_msg,"CO1"):  dp_j%=1
    WHEN FNmsg_0(psup%!CONST_psup_msg,"CO1s"): dp_j%=1
    WHEN FNmsg_0(psup%!CONST_psup_msg,"CO2"):  dp_j%=2
    WHEN FNmsg_0(psup%!CONST_psup_msg,"CO4"):  dp_j%=4
    WHEN FNmsg_0(psup%!CONST_psup_msg,"CO5"):  dp_j%=5
    WHEN FNmsg_0(psup%!CONST_psup_msg,"CO5s"): dp_j%=5
    OTHERWISE: dp_j%=0
  ENDCASE
  dp_s$=MID$(dp_s$,dp_i%+2)
  CASE dp_s$ OF
    WHEN FNmsg_0(psup%!CONST_psup_msg,"HT8"):  dp_i%=8
    WHEN FNmsg_0(psup%!CONST_psup_msg,"HT8s"): dp_i%=8
    WHEN FNmsg_0(psup%!CONST_psup_msg,"HT1"):  dp_i%=1
    WHEN FNmsg_0(psup%!CONST_psup_msg,"HT1s"): dp_i%=1
    OTHERWISE: dp_i%=4
  ENDCASE
  cnfg%!CONST_cnfg_dp_options=FNstore_integer((dp_i%<<8)+dp_j%)

  dp_j%=prnt%!CONST_prnt_psze
  dp_s$=FNicon_read(window%,27)
  IF $dp_j%!CONST_psze_name<>dp_s$ THEN
    dp_i%=psize_head%
    WHILE dp_i%
      IF $dp_i%!CONST_psze_name=dp_s$ THEN
        prnt%!CONST_prnt_psze=dp_i%
        dp_i%=0
      ELSE
        dp_i%=!dp_i%
      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): Don't do this - calls overlay
 */
  ENDIF
ENDPROC

DEF FNdp_res(cnfg%)
  LOCAL xres%,yres%,graphics_prdt%,nm$
  REM VDU: PROCftracef("FNdp_res")
  graphics_prdt%=!cnfg%!CONST_cnfg_dp_graphics
  xres%=FNprinter_read_integer_entry(graphics_prdt%,4)
  yres%=FNprinter_read_integer_entry(graphics_prdt%,5)
  nm$=FNprinter_read_string_entry(graphics_prdt%,8)
  IF nm$="" THEN  nm$=FNmsg_2(psup%!CONST_psup_msg,"RES",STR$ xres%,STR$ yres%)
=nm$

DEF FNdp_qual_name(dp_i%)
  LOCAL dp_s$,dp_t$
  IF DPQ$ = "S" THEN
    dp_s$=FNmsg_0(psup%!CONST_psup_msg,"CO"+STR$(dp_i% AND &FF)+"s")
    dp_t$=FNmsg_0(psup%!CONST_psup_msg,"HT"+STR$((dp_i% AND &FF00)>>8)+"s")
  ELSE
    dp_s$=FNmsg_0(psup%!CONST_psup_msg,"CO"+STR$(dp_i% AND &FF))
    dp_t$=FNmsg_0(psup%!CONST_psup_msg,"HT"+STR$((dp_i% AND &FF00)>>8))
  ENDIF
=dp_s$+", "+dp_t$

DEF FNdp_qual(cnfg%)
  LOCAL dp_i%
  REM VDU: PROCftracef("FNdp_qual")
  dp_i%=!cnfg%!CONST_cnfg_dp_options
=FNdp_qual_name(dp_i%)

DEF FNdp_get_quality_options(graphics_definition%)
LOCAL s%,c%,t%
s%=FNprinter_read_integer_entry(graphics_definition%,3)
REM if colour small halftone present, add colour large halftone
IF (s% AND &100) s% = s% OR &200
REM if colour available, add new colour options
IF (s% AND &700) THEN
 t%=FNprinter_read_integer_entry(graphics_definition%,1):REM ptr to module defn
 t%=FNprinter_read_integer_entry(t%,1):REM module number
 REM need to pass the MiscOp through to the dumper driver
 SYS"XPDriver_MiscOpForDriver",&80000002,t%,,,,,,,7 TO t%;c%:REM strip type mask
 IF(c%AND1)=0 AND t%<>&80000002 THEN
  IF (t% AND (1<<3)) THEN
   REM add strip type 3 based on the greyscale options (or colour, if no grey)
   c%=s% AND &70
   IF c%=0 THEN c%=(s% AND &700)>>4
   s%=s% OR (c%<<16)
  ENDIF
  IF (t% AND (1<<4)) THEN
/*   REM add strip type 4 based on the colour options */
   c%=s% AND &700
   s%=s% OR (c%<<8)
  ENDIF
  IF (t% AND (1<<5)) THEN
   REM add strip type 5 based on the colour options
   c%=s% AND &700
   s%=s% OR (c%<<12)
  ENDIF
 ENDIF
ENDIF
REM If simple qualities, knock out Mono,256 colours,32k colours
IF DPQ$ = "S" s%=s% AND &700070
=s%

REM If DPQ$ = "S" then the following qualities are
REM actually deemed not to exist:
REM - Any 'Mono'; '256 colours'; '32k colours'

REM This procedure tries to find a good default quality to pick.
REM Modified on 22-Jul-93/3-Dec-93 to pick in this order:
REM Modified on 02-Aug-95 to favour error diff instead of halftone
REM * 16 million, diffused
REM * colour, diffused
REM * grey, diffused
REM * mono, diffused
REM
REM The option value is split into 3 nibbles:
REM &7xxxxx = 24bpp colour, either strip type 3 or 5 depending on
REM                         whether or not it is a full colour system
REM &x7xxxx = 16bpp colour, strip type 4
REM &xxx7xx = colour, strip type 2
REM &xxxx7x = greyscale, strip type 1
REM &xxxxx7 = monochrome, strip type 0
REM
REM Within the 3 nibbles, the following values are valid:
REM 1 = small halftone, tone type 4
REM 2 = large halftone, tone type 8
REM 4 = dithered, tone type 1
DEF PROCdp_decode_options(option%,RETURN strip%,RETURN tone%)
  REM VDU: PROCftracef("PROCdp_decode_options")
  REM try to pick colour, then grey, then mono
  IF option% AND &700000 THEN
   strip%=5
  ELSE 
   IF option% AND &700 THEN
    strip%=2
   ELSE
    IF option% AND &70 THEN
     strip%=1
    ELSE
     REM force grey if Simple (Mono not allowed)
     IF DPQ$ = "S" THEN strip%=1 ELSE strip%=0
    ENDIF
   ENDIF
  ENDIF

/* REM find out what is available now */
  option%=option%>>(strip%*4)
  tone%=-1
  IF (strip%=5 AND (option% AND 4)<>0) tone%=1
  IF (strip%=2 AND (option% AND 4)<>0) tone%=1
  IF (strip%=1 AND (option% AND 4)<>0) tone%=1
  IF (strip%=0 AND (option% AND 4)<>0) tone%=1
/*
 * REM if we've failed now, try to pick
 * REM dithered, large halftone, small halftone
 */
  IF tone%=-1 THEN
    IF option% AND 4 THEN
      tone%=1
    ELSE
      IF option% AND 2 THEN
        tone%=8
      ELSE
        tone%=4
      ENDIF
    ENDIF
  ENDIF
ENDPROC

DEF PROCdp_menu(top$,rebuild%,iconpos%)
  LOCAL wind%,dp_ix%,dp_iy%,dp_i%,dp_x%,dp_j%,dp_k%,xres%,yres%,indt%
  REM VDU: PROCftracef("PROCdp_menu")
  IF rebuild% dp_menu_xpos%=xbuff%!0-64: dp_menu_ypos%=xbuff%!4
  IF iconpos% THEN
    !buff%=xbuff%!12:buff%!4=xbuff%!16:SYS"Wimp_GetIconState",,buff%
    dp_ix%=buff%!16:dp_iy%=buff%!20
    SYS"Wimp_GetWindowState",,buff%
    dp_menu_xpos%=buff%!20+buff%!4+dp_ix%+2
    dp_menu_ypos%=buff%!24+buff%!16+dp_iy%-2
  ENDIF
  wind%=FNprinter_find_window(prnt%,"configure")
  dp_menu_chsn$=top$
  REM because of the way the configuration window works,
  REM we have to adjust prdt% to point to the printer data
  REM record for the printer specified in the window, NOT
  REM the current printer.
  prdt%=FNprinter_find_prdata_entry(psup%,FNicon_read(wind%,6))
  CASE top$ OF
    WHEN "ME1"
      PROCmenu_create(dp_menu%,FNmsg_0(psup%!CONST_psup_msg,"ME1"))
      indt%=(dp_menu%!28 AND &100)<>0
      REM get the resolution strings for this printer
      dp_j%=prdt%!20: dp_i%=0: dp_x%=0
      WHILE dp_j%
        dp_k%=!dp_j%!CONST_lstd_1st
        xres%=FNprinter_read_integer_entry(dp_k%,4)
        yres%=FNprinter_read_integer_entry(dp_k%,5)
        nm$=FNprinter_read_string_entry(dp_k%,8)
        IF nm$<>"" THEN
          PROCmenu_item(dp_menu%,dp_i%,nm$,indt%)
        ELSE
          PROCmenu_item(dp_menu%,dp_i%,FNmsg_2(psup%!CONST_psup_msg,"RES",STR$ xres%,STR$ yres%),indt%)
        ENDIF
        dp_i%+=1
        dp_j%=!dp_j%
      ENDWHILE
      PROCmenu_tick_match(dp_menu%,FNicon_read(wind%,3))
    WHEN "ME2"
      IF FNprinter_read_string_entry(prdt%,13)="" THEN
        PROCmenu_create(dp_menu%,FNmsg_0(psup%!CONST_psup_msg,"ME2"))
        PROCmenu_tick_match(dp_menu%,FNicon_read(wind%,17))
      ELSE
        PROCdp_binfeed_menu(dp_menu%,"ME2b","Feeds",FNprinter_read_string_entry(prdt%,13))
        PROCmenu_tick_match(dp_menu%,FNicon_read(wind%,17))
      ENDIF
    WHEN "ME3"
      PROCmenu_create(dp_menu%,FNmsg_0(psup%!CONST_psup_msg,"ME3"))
      REM need to find the right graphics entry for the current resolution
      dp_j%=prdt%!20: REM point to first record for this list
      WHILE dp_j%
        dp_k%=!dp_j%!CONST_lstd_1st
        IF (FNicon_read(wind%,3)=FNmsg_2(psup%!CONST_psup_msg,"RES",STR$ !dp_k%!20,STR$ !dp_k%!24)) OR \
           (FNicon_read(wind%,3)=$(dp_k%!36)) THEN
          REM ok - found the graphics entry, now get the options word
          dp_j%=FNdp_get_quality_options(dp_k%): dp_i%=0: dp_x%=0
          IF dp_j% AND &000007 PROCdp_menu_quality(dp_menu%,dp_i%,FNmsg_0(psup%!CONST_psup_msg,"CO0"),dp_j%)
          IF dp_j% AND &000070 THEN
            IF DPQ$="S" THEN
              PROCdp_menu_quality(dp_menu%,dp_i%,FNmsg_0(psup%!CONST_psup_msg,"CO1s"),dp_j%>>4)
            ELSE
              PROCdp_menu_quality(dp_menu%,dp_i%,FNmsg_0(psup%!CONST_psup_msg,"CO1"),dp_j%>>4)
            ENDIF
          ENDIF
          IF dp_j% AND &000700 PROCdp_menu_quality(dp_menu%,dp_i%,FNmsg_0(psup%!CONST_psup_msg,"CO2"),dp_j%>>8)
          IF dp_j% AND &070000 PROCdp_menu_quality(dp_menu%,dp_i%,FNmsg_0(psup%!CONST_psup_msg,"CO4"),dp_j%>>16)
          IF dp_j% AND &700000 THEN
            IF DPQ$="S" THEN
              PROCdp_menu_quality(dp_menu%,dp_i%,FNmsg_0(psup%!CONST_psup_msg,"CO5s"),dp_j%>>20)
            ELSE
              PROCdp_menu_quality(dp_menu%,dp_i%,FNmsg_0(psup%!CONST_psup_msg,"CO5"),dp_j%>>20)
            ENDIF
          ENDIF
          dp_j%=0
        ELSE
          dp_j%=!dp_j%
        ENDIF
      ENDWHILE
      PROCmenu_tick_match(dp_menu%,FNicon_read(wind%,15))
    WHEN "ME4"
      PROCmenu_create(dp_menu%,FNmsg_0(psup%!CONST_psup_msg,"ME4"))
      indt%=(dp_menu%!28 AND &100)<>0
      IF FNprinter_read_list_integer_entry(prdt%,5,2,1)THEN
        REM we have draft highlights
        PROCmenu_item(dp_menu%,1,FNmsg_0(psup%!CONST_psup_msg,"TQ1"),indt%)
        IF FNprinter_read_list_integer_entry(prdt%,5,3,1)PROCmenu_item(dp_menu%,2,FNmsg_0(psup%!CONST_psup_msg,"TQ2"),indt%)
      ENDIF
      PROCmenu_tick_match(dp_menu%,FNicon_read(wind%,14))
    WHEN "ME5"
      PROCmenu_create(dp_menu%,FNmsg_0(psup%!CONST_psup_msg,"ME5"))
      PROCmenu_tick_match(dp_menu%,FNicon_read(wind%,23))
    WHEN "ME6"
      PROCdp_binfeed_menu(dp_menu%,"ME6","Bins",FNprinter_read_string_entry(prdt%,14))
      PROCmenu_tick_match(dp_menu%,FNicon_read(wind%,37))
    WHEN "MP1"
      PROCcreate_paper_menu(dp_menu%,wind%,27)
  ENDCASE
  PROCdisplay_menu(prnt%,dp_menu%,dp_menu_xpos%,dp_menu_ypos%)
ENDPROC

DEF PROCdp_menu_quality(RETURN dp_menu%,RETURN dp_i%,strip$,tone%)
  LOCAL indt%
  REM VDU: PROCftracef("PROCdp_menu_quality")
  indt%=(dp_menu%!28 AND &100)<>0
  IF tone% AND 1 THEN
    IF DPQ$="S" THEN
      PROCmenu_item(dp_menu%,dp_i%,strip$+", "+FNmsg_0(psup%!CONST_psup_msg,"HT4s"),indt%)
    ELSE
      PROCmenu_item(dp_menu%,dp_i%,strip$+", "+FNmsg_0(psup%!CONST_psup_msg,"HT4"),indt%)
    ENDIF
    dp_i%+=1
  ENDIF
  IF tone% AND 2 THEN
    IF DPQ$="S" THEN
      PROCmenu_item(dp_menu%,dp_i%,strip$+", "+FNmsg_0(psup%!CONST_psup_msg,"HT8s"),indt%)
    ELSE
      PROCmenu_item(dp_menu%,dp_i%,strip$+", "+FNmsg_0(psup%!CONST_psup_msg,"HT8"),indt%)
    ENDIF
    dp_i%+=1
  ENDIF
  IF tone% AND 4 THEN
    IF DPQ$="S" THEN
      PROCmenu_item(dp_menu%,dp_i%,strip$+", "+FNmsg_0(psup%!CONST_psup_msg,"HT1s"),indt%)
    ELSE
      PROCmenu_item(dp_menu%,dp_i%,strip$+", "+FNmsg_0(psup%!CONST_psup_msg,"HT1"),indt%)
    ENDIF
    dp_i%+=1
  ENDIF
ENDPROC

DEF FNdp_hex2(v%)
  REM VDU: PROCftracef("FNdp_hex2")
=RIGHT$("0"+STR$~v%,2)

REM text printing code

DEF PROCdp_m8
  LOCAL dp_r%,queu%,tpub%,tprv%,text_prdt%
  REM VDU: PROCftracef("PROCdp_m8, reason "+STR$!xbuff%)
  REM VDU: PROCftracef(STR$~cnfg%)
  REM VDU: PROCftracef(STR$~cnfg%!CONST_cnfg_dp_text)
  REM VDU: PROCftracef(STR$~!cnfg%!CONST_cnfg_dp_text)
  text_prdt%=!cnfg%!CONST_cnfg_dp_text
  dp_r%=!xbuff%
  queu%=xbuff%!4
  tpub%=queu%!CONST_queu_tpub
  tprv%=queu%!CONST_queu_tprv
  CASE dp_r% OF
    WHEN  -1: PROCdp_1
    WHEN  -2: PROCdp_2
    WHEN  -4: PROCdp_4
    WHEN  -6: PROCdp_6
    WHEN  -7: PROCdp_7
    WHEN  -9: PROCdp_9
    WHEN -10: PROCdp_10
    WHEN -11: PROCdp_11
    WHEN -12: PROCdp_12
    WHEN -13: PROCdp_13
    WHEN -15: PROCdp_15
    WHEN -16: PROCdp_16
    WHEN -17: PROCdp_17
    WHEN -18: PROCdp_18
    WHEN -19: PROCdp_19
  ENDCASE
  REM VDU: PROCftracef("Afterwards ...")
  REM VDU: PROCftracef(STR$~cnfg%)
  REM VDU: PROCftracef(STR$~cnfg%!CONST_cnfg_dp_text)
  REM VDU: PROCftracef(STR$~!cnfg%!CONST_cnfg_dp_text)
ENDPROC

DEF PROCdp_1
/*  REM only called if we aren't printing a DP file */
  LOCAL dp_i%,dp_i$,psze%,dp_j%,B%,C%,D%
  REM VDU: PROCftracef("PROCdp_1")
  B%=CONST_ident_TPRV:C%=CONST_tprv_dp_MAX
  tprv%=USR(code_entry%+CONST_entry_heap_claim)
  IFtprv%=0 ERROR CONST_error_fatal, FNmsg_0(FNdp_host_desc,"FA5")
  queu%!CONST_queu_tprv=tprv%
  FOR dp_i%=0 TO CONST_tprv_dp_MAX-4
    tprv%!dp_i%=0
  NEXT
  psze%=prnt%!CONST_prnt_psze
  tprv%!CONST_tprv_dp_left_print=psze%!CONST_psze_tleft
  dp_j%=!cnfg%!CONST_cnfg_dp_flags
  tpub%!CONST_tpub_cc_print=(dp_j% AND &FF00)>>8
  IF dp_j% AND 4 tpub%!CONST_tpub_number_print=TRUE
  IF dp_j% AND 2 tpub%!CONST_tpub_title_print=TRUE
  IF(dp_j%>>CONST_dp_flags_feed_offset AND CONST_dp_flags_feed_width)=CONST_dp_flags_feed_manual tpub%!CONST_tpub_manual_flag=TRUE
  REM set the line epilogue string
  IF dp_j% AND 8 THEN
    dp_i$=FNprinter_read_string_entry(text_prdt%,6)
  ELSE
    dp_i$=FNprinter_read_string_entry(text_prdt%,5)
  ENDIF
  B%=A%!CONST_interface_scratch
  $B%=dp_i$
  C%=5
  D%=LEN dp_i$
  tpub%!CONST_tpub_line_epilogue=USR(code_entry%+CONST_entry_store_string)
  dp_i$=STRING$(psze%!CONST_psze_ttop,dp_i$)
  $B%=dp_i$
  C%=5
  D%=LEN dp_i$
  tprv%!CONST_tprv_dp_page_prologue=USR(code_entry%+CONST_entry_store_string)
  tprv%!CONST_tprv_dp_height_print=psze%!CONST_psze_theight
  tpub%!CONST_tpub_line_max=psze%!CONST_psze_theight-psze%!CONST_psze_ttop-psze%!CONST_psze_tbottom
  REM set the pointer to the char translation list
  dp_j%=FNprinter_read_integer_entry(prdt%,6): REM point to the PRDT block
  IF dp_j% dp_j%=dp_j%!CONST_prdt_1st
  queu%!CONST_queu_char=dp_j%
ENDPROC

DEF PROCdp_2
  LOCAL dp_s$,pheight%,graphics_prdt%
  REM VDU: PROCftracef("PROCdp_2")
  REM output job start string
  dp_s$=FNprinter_read_string_entry(text_prdt%,7)
  IF dp_s$<>"" BPUT#xbuff%!8,dp_s$;
  dp_s$=FNprinter_read_string_entry(text_prdt%,1)
  pheight%=prnt%!CONST_prnt_psze
  pheight%=pheight%!CONST_psze_theight

  REM Ouput set lines if both string exists and page length is not zero.
  REM OSS Kludge - if dumper name = "PDumperIW" then output as 144ths of
  REM an inch as a four digit decimal number with leading zeros. Assume
 REM 6 lines per inch, 144/6 = 24.

  IF dp_s$<>"" AND pheight%<>0 THEN
    graphics_prdt%=!cnfg%!CONST_cnfg_dp_graphics
    IF FNprinter_read_string_entry(FNprinter_read_integer_entry(graphics_prdt%,1),2)="PDumperIW" THEN
      dp_s$+="0000"
      RIGHT$(dp_s$,4)=STR$(pheight%*24)
      BPUT#xbuff%!8,dp_s$;
    ELSE
      BPUT#xbuff%!8,dp_s$+CHR$(pheight%);
    ENDIF
  ENDIF
ENDPROC

DEF PROCdp_4
  REM no data to output
  REM VDU: PROCftracef("PROCdp_4")
  xbuff%?8=0
ENDPROC

DEF PROCdp_6
  REM do control code processing
  LOCAL dp_b$
  REM VDU: PROCftracef("PROCdp_6")
  dp_b$=FNdp_display(xbuff%!8)
  xbuff%?8=LEN dp_b$
  $(xbuff%+9)=dp_b$
ENDPROC

DEF PROCdp_7
  REM process a backspace
  LOCAL dp_b$
  REM VDU: PROCftracef("PROCdp_7")
  dp_b$=FNprinter_read_string_entry(text_prdt%,2)
  xbuff%?8=LEN dp_b$
  $(xbuff%+9)=dp_b$
ENDPROC

DEF PROCdp_9
  LOCAL changed_bits%,clr_bits%,set_bits%,bit%,dp_b$
  REM VDU: PROCftracef("PROCdp_9")
  changed_bits%=tpub%!CONST_tpub_style_bits EOR xbuff%!8
  clr_bits%=tpub%!CONST_tpub_style_bits AND changed_bits%
  set_bits%=changed_bits% AND NOTclr_bits%
  IF clr_bits% OR set_bits% THEN
    FOR bit%=0 TO 5
      IF clr_bits% AND 1<<bit% THEN dp_b$+=FNdp_style_off(bit%)
      IF set_bits% AND 1<<bit% THEN dp_b$+=FNdp_style_on(bit%)
    NEXT
  ENDIF
  xbuff%?8=LEN dp_b$
  $(xbuff%+9)=dp_b$
ENDPROC

DEF PROCdp_10
  REM start a new line
  LOCAL dp_s$,dp_b$
  REM VDU: PROCftracef("PROCdp_10")
  tpub%!CONST_tpub_line_page+=1
  tpub%!CONST_tpub_line_doc+=1
  IF tpub%!CONST_tpub_number_print<>0 OR tprv%!CONST_tprv_dp_left_print>0 THEN
    dp_b$=FNdp_font(0): REM pica
    FOR bit%=0 TO 5
     IF tpub%!CONST_tpub_style_bits AND 1<<bit% dp_b$+=FNdp_style_off(bit%)
    NEXT
    dp_b$+=STRING$(tprv%!CONST_tprv_dp_left_print," ")
    IF tpub%!CONST_tpub_number_print THEN
      dp_s$=STR$ tpub%!CONST_tpub_line_doc
      dp_b$+=STRING$(5-LEN dp_s$," ")+dp_s$+" "
    ENDIF
    FOR bit%=0 TO 5
      IF tpub%!CONST_tpub_style_bits AND 1<<bit% dp_b$+=FNdp_style_on(bit%)
    NEXT
  ENDIF
  dp_b$+=FNdp_font(tpub%!CONST_tpub_font_num)+STRING$(tprv%!CONST_tprv_dp_left_ruler," ")
  xbuff%?8=LEN dp_b$
  $(xbuff%+9)=dp_b$
ENDPROC

DEF PROCdp_11
  LOCAL dp_b$,dp_i%
  REM VDU: PROCftracef("PROCdp_11")
  PROCdp_10:dp_b$=FNprinter_read_string(tpub%!CONST_tpub_line_epilogue)+$(xbuff%+9)
  PROCdp_10:dp_b$+=FNprinter_read_string(tpub%!CONST_tpub_line_epilogue)+$(xbuff%+9)
  dp_b$+=FNdp_style_on(4): REM superscript
  dp_b$+=FNdp_trans(RIGHT$("  "+STR$ tpub%!CONST_tpub_footnote_num,3)+STRING$(3,FNprinter_read_string_entry(text_prdt%,2)))
  dp_b$+=FNdp_style_off(4)
  xbuff%?8=LEN dp_b$
  $(xbuff%+9)=dp_b$
ENDPROC

DEF PROCdp_12
  LOCAL dp_b$
  REM VDU: PROCftracef("PROCdp_12")
  dp_b$=FNdp_trans($(xbuff%+8))
  xbuff%?8=LEN dp_b$
  $(xbuff%+9)=dp_b$
ENDPROC

DEF PROCdp_13
  REM VDU: PROCftracef("PROCdp_13")
  tpub%!CONST_tpub_font_num=xbuff%!8
  xbuff%?8=0
ENDPROC

DEF PROCdp_15
/*  REM end of job */
  LOCAL text_prdt%,tpub%,dp_epilogue$,dp_formfeed$,dp_lineepi$
  REM VDU: PROCftracef("PROCdp_15")
  IF queu%!CONST_queu_type<>&FF4 THEN
    text_prdt%=!cnfg%!CONST_cnfg_dp_text
    tpub%=queu%!CONST_queu_tpub
    dp_lineepi$=FNprinter_read_string(tpub%!CONST_tpub_line_epilogue)
    IF queu%!CONST_queu_type=&FFF THEN
/*
 *     REM if the page pause flag is true, it means that the user stopped
 *     REM the printing, so don't bother to tidy up
 */
      IF(tpub%!CONST_tpub_pause_flag)=0 THEN
        dp_epilogue$=FNprinter_read_string_entry(text_prdt%,8)
        dp_formfeed$=FNprinter_read_string_entry(text_prdt%,4)
        IF INSTR(dp_epilogue$,dp_lineepi$)<>1 THEN
          IF dp_lineepi$<>"" BPUT#xbuff%!8,dp_lineepi$;
        ENDIF
        IF dp_epilogue$<>"" BPUT#xbuff%!8,dp_epilogue$;
      ENDIF
    ELSE
      REM output a blank line between files
      IF dp_lineepi$<>"" BPUT#xbuff%!8,dp_lineepi$;
    ENDIF
  ENDIF
ENDPROC

DEF PROCdp_16
  REM process a tab
  LOCAL dp_b$
  REM VDU: PROCftracef("PROCdp_16")
  dp_b$=FNprinter_read_string_entry(text_prdt%,3)
  xbuff%?8=LEN dp_b$
  $(xbuff%+9)=dp_b$
ENDPROC

DEF PROCdp_17
  REM do a formfeed
  LOCAL dp_b$
  REM VDU: PROCftracef("PROCdp_17")
  dp_b$=FNprinter_read_string_entry(text_prdt%,4)
  xbuff%?8=LEN dp_b$
  $(xbuff%+9)=dp_b$
ENDPROC

DEF PROCdp_18
  REM change layout
  LOCAL layout_height%,layout_top%,layout_bottom%,dp_b$,dp_i%,dp_i$,B%,C%,D%,graphics_prdt%
  REM VDU: PROCftracef("PROCdp_18")
  layout_height%=xbuff%!8
  layout_top%=xbuff%!12
  layout_bottom%=xbuff%!16
  IF layout_height%<=tprv%!CONST_tprv_dp_height_print AND layout_top%<=layout_height%*0.33 AND layout_bottom%<=layout_height%*0.33 THEN
    tpub%!CONST_tpub_line_max=layout_height%-layout_top%-layout_bottom%
    IF tprv%!CONST_tprv_dp_page_prologue THEN
      REM VDU: PROCftracef("Calling heap free with ptr "+STR$~tprv%!CONST_tprv_dp_page_prologue)
      B%=CONST_ident_GSTR
      C%=tprv%!CONST_tprv_dp_page_prologue
      CALL code_entry%+CONST_entry_heap_free
    ENDIF
    dp_i$=STRING$(layout_top%,FNprinter_read_string(tpub%!CONST_tpub_line_epilogue))
    B%=A%!CONST_interface_scratch
    $B%=dp_i$
    C%=5
    D%=LEN dp_i$
    tprv%!CONST_tprv_dp_page_prologue=USR(code_entry%+CONST_entry_store_string)
    dp_b$=FNprinter_read_string_entry(text_prdt%,1): REM text_page_line

    REM OSS Kludge - if dumper name = "PDumperIW" then output as 144ths of
    REM an inch as a four digit decimal number with leading zeros. Assume
    REM 6 lines per inch, 144/6 = 24.

    IF dp_b$<>"" AND layout_height%<>0 THEN
      graphics_prdt%=!(cnfg%!CONST_cnfg_dp_graphics)
      IF FNprinter_read_string_entry(FNprinter_read_integer_entry(graphics_prdt%,1),2)="PDumperIW" THEN
        dp_b$+="0000"
        RIGHT$(dp_b$,4)=STR$(layout_height%*24)
      ELSE
        dp_b$+=CHR$ layout_height%
      ENDIF
    ENDIF
  ENDIF
  xbuff%?8=LEN dp_b$
  $(xbuff%+9)=dp_b$
ENDPROC

DEF PROCdp_19
  REM VDU: PROCftracef("PROCdp_19")
  LOCAL dp_b$,dp_i%,dp_s$,bit%
  dp_b$=FNprinter_read_string(tprv%!CONST_tprv_dp_page_prologue)
  tpub%!CONST_tpub_line_page=0
  tpub%!CONST_tpub_page_num+=1
  IF tpub%!CONST_tpub_title_print THEN
    tpub%!CONST_tpub_line_page+=2
    dp_b$+=FNdp_font(0): REM pica
    FOR bit%=0 TO 5
     IF tpub%!CONST_tpub_style_bits AND 1<<bit% dp_b$+=FNdp_style_off(bit%)
    NEXT
    dp_b$+=STRING$(tprv%!CONST_tprv_dp_left_print+tprv%!CONST_tprv_dp_left_ruler," ")
    dp_s$=FNprinter_read_string(tpub%!CONST_tpub_name)+"   "+FNprinter_read_string(tpub%!CONST_tpub_time)
    dp_s$+="   "+FNmsg_1(psup%!CONST_psup_msg,"PAG",STR$ tpub%!CONST_tpub_page_num)
    dp_b$+=FNdp_trans(dp_s$)
    FOR bit%=0 TO 5
      IF tpub%!CONST_tpub_style_bits AND 1<<bit% dp_b$+=FNdp_style_on(bit%)
    NEXT
    dp_b$+=STRING$(2,FNprinter_read_string(tpub%!CONST_tpub_line_epilogue))
  ENDIF
  xbuff%?8=LEN dp_b$
  $(xbuff%+9)=dp_b$
ENDPROC

DEF FNdp_trans(dp_s$)
  LOCAL dp_i%,byte%,out$,str$
  REM VDU: PROCftracef("FNdp_trans")
  IF dp_s$="" THEN =""
  FOR dp_i%=1 TO LEN dp_s$
    byte%=ASC MID$(dp_s$,dp_i%,1)
    str$=""
    CASE TRUE OF
      WHEN byte%<32 OR byte%=127
        IF tpub%!CONST_tpub_cc_print=1 str$=FNdp_display(byte%)
      WHEN byte%>127 AND tpub%!CONST_tpub_cc_print<>0
        IF tpub%!CONST_tpub_cc_print=1 str$=FNdp_display(byte%)
      WHEN tpub%!CONST_tpub_cc_print<>0
        str$=CHR$ byte%
      OTHERWISE
        str$=FNdp_text_char(byte%)
        IF str$="" str$=CHR$ byte%
    ENDCASE
    out$+=str$
  NEXT
=out$

DEF FNdp_text_char(byte%)
  LOCAL dp_p%,dp_s$,dp_i%
  REM VDU: PROCftracef("FNdp_text_char")
  dp_p%=queu%!CONST_queu_char
  WHILE dp_p%
    CASE TRUE OF
      WHEN dp_p%?4=byte%
        dp_i%=dp_p%?5:dp_p%=dp_p%+6
        WHILE dp_i%
          dp_s$+=CHR$ ?dp_p%
          dp_p%+=1
          dp_i%-=1
        ENDWHILE
        =dp_s$
      WHEN dp_p%?4>byte%
        dp_p%=0
      OTHERWISE
        dp_p%=!dp_p%
    ENDCASE
  ENDWHILE
=""

DEF FNdp_display(byte%)
  REM VDU: PROCftracef("FNdp_display")
="["+RIGHT$("0"+FNtask_lower(STR$~byte%),2)+"]"

DEF FNdp_style_on(bit%)
  REM VDU: PROCftracef("FNdp_style_on")
  CASE bit% OF
    WHEN 0: =FNprinter_read_string_entry(text_prdt%,13): REM bold on
    WHEN 1: =FNprinter_read_string_entry(text_prdt%,17): REM light on
    WHEN 2: =FNprinter_read_string_entry(text_prdt%,15): REM italic on
    WHEN 3: =FNprinter_read_string_entry(text_prdt%,23): REM underline on
    WHEN 4: =FNprinter_read_string_entry(text_prdt%,19): REM superscript on
    WHEN 5: =FNprinter_read_string_entry(text_prdt%,21): REM subscript on
  ENDCASE
=""
:
DEF FNdp_style_off(bit%)
  REM VDU: PROCftracef("FNdp_style_off")
  CASE bit% OF
    WHEN 0: =FNprinter_read_string_entry(text_prdt%,14): REM bold off
    WHEN 1: =FNprinter_read_string_entry(text_prdt%,18): REM light off
    WHEN 2: =FNprinter_read_string_entry(text_prdt%,16): REM italic off
    WHEN 3: =FNprinter_read_string_entry(text_prdt%,24): REM underline off
    WHEN 4: =FNprinter_read_string_entry(text_prdt%,20): REM superscript off
    WHEN 5: =FNprinter_read_string_entry(text_prdt%,22): REM subscript off
  ENDCASE
=""

DEF FNdp_font(font%)
  REM VDU: PROCftracef("FNdp_font")
  CASE font% OF
    WHEN 0: =FNprinter_read_string_entry(text_prdt%,9):REM pica
    WHEN 1: =FNprinter_read_string_entry(text_prdt%,10):REM elite
    WHEN 2: =FNprinter_read_string_entry(text_prdt%,11):REM condensed
    WHEN 3: =FNprinter_read_string_entry(text_prdt%,12):REM expanded
  ENDCASE
=""

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

DEF FNdp_get_feed_name(dp_dir$,dp_j%)
=FNdp_get_gen_name(dp_dir$,dp_j%,"Feeds")

DEF FNdp_get_bin_name(dp_dir$,dp_j%)
=FNdp_get_gen_name(dp_dir$,dp_j%,"Bins")

DEF FNdp_get_gen_name(dp_dir$,dp_j%,dp_t$)
=FNget_gen_name("dp",dp_dir$,dp_j%,dp_t$,buff%)

DEF FNdp_feed_strings
  LOCAL dp_s$,dp_j%
  IF FNprinter_read_string_entry(prdt%,13)<>"" THEN
    dp_j%=!cnfg%!CONST_cnfg_dp_flags
    dp_j%=(dp_j% AND &1F80000)>>19
    dp_s$=FNdp_gen_strings(dp_j%,"Feeds",FNprinter_read_string_entry(prdt%,13))
  ELSE
    IF !cnfg%!CONST_cnfg_dp_flags AND 1 THEN
      dp_s$=FNmsg_0(psup%!CONST_psup_msg,"MANUAL_FEED")
    ELSE
      dp_s$=FNmsg_0(psup%!CONST_psup_msg,"AUTO_FEED")
    ENDIF
  ENDIF
=dp_s$

DEF FNdp_bin_strings
  LOCAL dp_s$,dp_j%
  IF FNprinter_read_string_entry(prdt%,14)<>"" THEN
    dp_j%=!cnfg%!CONST_cnfg_dp_flags
    dp_j%=(dp_j% AND &7E000000)>>25
    dp_s$=FNdp_gen_strings(dp_j%,"Bins",FNprinter_read_string_entry(prdt%,14))
  ELSE
    dp_s$=""
  ENDIF
=dp_s$

DEF FNdp_gen_strings(dp_j%,dp_t$,dp_dir$)
=FNgen_strings("dp",dp_j%,dp_t$,dp_dir$,buff%)

DEF PROCdp_binfeed_menu(RETURN dp_menu%,dp_s$,dp_t$,t$)
PROCbinfeed_menu("dp",dp_menu%,dp_s$,dp_t$,t$,buff%)
ENDPROC

DEF FNdp_binfeed_save(dp_dir$,dp_s$,dp_t$)
=FNbinfeed_save("dp",dp_dir$,dp_s$,dp_t$,buff%)
