REM > Support - for Laser/Desk Jet 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 FNlj_support(buff%)
  LOCAL reason%,psup%,prnt%,prdt%,cnfg%,xbuff%,psize_head%,code_entry%
  REM VDU: PROCftracef("PROClj_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: PROClj_m1
    WHEN -2: PROClj_m2
    WHEN -3: PROClj_m3
    WHEN -4: PROClj_m4
    WHEN -5: PROClj_m5
    WHEN -6: PROClj_m6
    WHEN -7: PROClj_m7
    WHEN -8: PROClj_m8
    WHEN 3: PROClj_p3
    WHEN 6: PROClj_p6
    WHEN 8: PROClj_p8
    WHEN 9: PROClj_p9
    WHEN 17,18: PROClj_p17
  ENDCASE
=FALSE

DEF PROClj_m1
  LOCAL colours%, pdriverdp%, exists%
  REM psup%!CONST_psup_flags OR= 0
  REM VDU: PROCftracef("PROClj_m1")
  psup%!CONST_psup_type=&FF4
  psup%!CONST_psup_text=%1001
  psup%!CONST_psup_cnfg=CONST_cnfg_lj_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(FNlj_host_desc,"WA12"), 1 OR 1<<4,FNmsg_1(FNlj_host_desc,"ER2",FNmsg_0(FNlj_host_desc,"ID"))
  ENDIF
/* do not allow this any more
  SYS "XOS_ReadVarVal","Printers$DPLJfullQ",,-1,,3 TO,,exists%
  IF exists% THEN LJQ$="F" ELSE LJQ$="S"
*/
LJQ$="S"
ENDPROC

DEF PROClj_m2
  REM VDU: PROCftracef("PROClj_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 PROClj_m3
  REM initialise the configuration window
  LOCAL config%,lj_i%,lj_j%
  REM VDU: PROCftracef("PROClj_m3")
  config%=FNprinter_find_window(prnt%,"configure")
  PROCicon_write(config%,27,FNprinter_read_string(prnt%!CONST_prnt_name))
  PROCicon_write(config%,6,$prnt%!CONST_prnt_type)
  PROCicon_write(config%,3,FNlj_res(cnfg%))
  PROCicon_write(config%,15,FNlj_qual(cnfg%))
  lj_i%=!cnfg%!CONST_cnfg_lj_flags
  IF FNprinter_read_string_entry(prdt%,13)<>"" THEN
    /* Special list of feeds */
    lj_j%=(lj_i% AND 1) + ((lj_i% AND &1F0000)>>15)
    PROCicon_write(config%,17,FNlj_get_feed_name(FNprinter_read_string_entry(prdt%,13),lj_j%))
  ELSE
    /* Just the usual Auto/Manual feeds then. */
    PROCicon_write(config%,17,FNmsg_0(psup%!CONST_psup_msg,"PF"+STR$ lj_j%))
  ENDIF
  IF FNprinter_read_string_entry(prdt%,14)<>"" THEN
    lj_j%=(lj_i% AND &7E00000)>>21
    PROCicon_write(config%,35,FNlj_get_bin_name(FNprinter_read_string_entry(prdt%,14),lj_j%))
    PROCicon_unshade(config%,36)
  ELSE
    PROCicon_write(config%,35,FNmsg_0(psup%!CONST_psup_msg,"OB0"))
    PROCicon_shade(config%,36)
  ENDIF
  IF FNhas_external_config_app(prnt%) THEN
    PROCicon_unshade(config%,33)
  ELSE
    PROCicon_shade(config%,33)
  ENDIF
  IF prnt%!CONST_prnt_flags AND 1<<6 THEN
    PROCicon_shade(config%,8)
    PROCicon_shade(config%,11)
    PROCicon_shade(config%,13)
    PROCicon_shade(config%,14)
    PROCicon_shade(config%,22)
    PROCicon_shade(config%,23)
  ELSE
    PROCicon_unshade(config%,8)
    PROCicon_unshade(config%,11)
    PROCicon_unshade(config%,13)
    PROCicon_unshade(config%,14)
    PROCicon_unshade(config%,22)
    PROCicon_unshade(config%,23)
    lj_j%=lj_i% AND %000010
    IF lj_j% PROCicon_select(config%,8)ELSE PROCicon_deselect(config%,8)
    lj_j%=lj_i% AND %000100
    IF lj_j% PROCicon_select(config%,11)ELSE PROCicon_deselect(config%,11)
    lj_j%=lj_i% AND %001000
    PROCicon_write(config%,13,FNmsg_0(psup%!CONST_psup_msg,"PO"+STR$(lj_j%>>3)))
    lj_j%=(lj_i% AND &F00)>>8
    PROCicon_write(config%,22,FNmsg_0(psup%!CONST_psup_msg,"CC"+STR$ lj_j%))
  ENDIF
  lj_i%=prnt%!CONST_prnt_psze
  PROCicon_write(config%,25,$lj_i%!CONST_psze_name)
ENDPROC

DEF PROClj_m4
  REM create a CNFG block with suitable defaults
  LOCAL lj_s$,lj_nm$,lj_nm2$,lj_i%,lj_s%,lj_t%,lj_x%,lj_y%,lj_co%,lj_ht%,B%,C%
  REM VDU: PROCftracef("PROClj_m4")
  REM PJC: set the text options to be draft
  cnfg%!CONST_cnfg_lj_flags=FNstore_integer(%010000)
  REM portrait mode is no-highlights entry
  lj_i%=FNprinter_read_list_integer_entry(prdt%,5,1,1)
  IF lj_i% THEN
    B%=CONST_ident_POTR
    C%=4
    cnfg%!CONST_cnfg_lj_text=USR(code_entry%+CONST_entry_heap_claim)
    IF cnfg%!CONST_cnfg_lj_text=0 ERROR CONST_error_fatal, FNmsg_0(FNlj_host_desc,"FA5")
    !cnfg%!CONST_cnfg_lj_text=lj_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
  lj_x%=FNprinter_read_integer_entry(prdt%,8)
  lj_y%=FNprinter_read_integer_entry(prdt%,9)
  lj_nm$=FNprinter_read_string_entry(prdt%,12)
  IF lj_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
        lj_nm2$=FNprinter_read_string_entry(B%,8)
        REM if no match, try the next mode
        IFlj_nm$<>lj_nm2$ C%+=1
      ENDIF
    UNTIL C%=-1 OR lj_nm$=lj_nm2$
    REM if we found it, remember where it was
    IF C%<>-1 lj_i%=C%
  ELSE
    IF (lj_x%<>0 AND lj_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
          lj_s%=FNprinter_read_integer_entry(B%,4)
          lj_t%=FNprinter_read_integer_entry(B%,5)
          REM if no match, try the next mode
          IFlj_s%<>lj_x% OR lj_t%<>lj_y% C%+=1
        ENDIF
      UNTIL C%=-1 OR (lj_s%=lj_x% AND lj_t%=lj_y%)
      REM if we found it, remember where it was
      IF C%<>-1 lj_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 set the graphics options to be the closest resolution to 300 x 300
 */
  IF C%=-1 THEN
    C%=1
    lj_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: lj_i%=TRUE
      ELSE
        lj_x%=FNprinter_read_integer_entry(B%,4)
        lj_y%=FNprinter_read_integer_entry(B%,5)
        IF lj_x%<300 OR lj_y%<300 C%+=1 ELSE lj_i%=TRUE
      ENDIF
    UNTIL lj_i%
    lj_i%=C%
  ENDIF

  B%=CONST_ident_POTR
  C%=4
  cnfg%!CONST_cnfg_lj_graphics=USR(code_entry%+CONST_entry_heap_claim)
  IF cnfg%!CONST_cnfg_lj_graphics=0 ERROR CONST_error_fatal, FNmsg_0(FNlj_host_desc,"FA5")
  !cnfg%!CONST_cnfg_lj_graphics=FNprinter_read_list_integer_entry(prdt%,4,lj_i%,1)

  REM ensure that the module is present in memory
  lj_s$=FNprinter_read_string_entry(FNprinter_read_integer_entry(!cnfg%!CONST_cnfg_lj_graphics,1),2)
  IFFNrmload_latest_module(lj_s$, "Printers:PDumpers."+lj_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
  lj_s$=STR$(FNprinter_read_integer_entry(!cnfg%!CONST_cnfg_lj_graphics,2) AND &7FFFFF)
  PROClj_ensure_resource_file("Resources.Printers.Palettes."+lj_s$,"Printers:Palettes."+lj_s$,!cnfg%!CONST_cnfg_lj_graphics)

  REM initialise the quality
  REM see if a quality was provided in the PDF
  lj_i%=FNprinter_read_integer_entry(prdt%,10)
  REM get the qualities available at the configured resolution
  lj_s%=FNlj_get_quality_options(!cnfg%!CONST_cnfg_lj_graphics)
  IF lj_i%<>0 THEN
/*
 *   REM validate values! reset lj_i% to zero if the requested
 *   REM colour and halftone type aren't available at the specified
 *   REM resolution
 */
    lj_co%=lj_i% AND &FF
    lj_ht%=(lj_i% AND &FF00)>>8
    CASE lj_co% OF
      WHEN 0: REM mono
        IF (lj_s% AND 7) THEN
          IF lj_ht%=4 AND (lj_s% AND 1)=0 lj_i%=0
          IF lj_ht%=8 AND (lj_s% AND 2)=0 lj_i%=0
          IF lj_ht%=1 AND (lj_s% AND 4)=0 lj_i%=0
        ELSE
          lj_i%=0
        ENDIF
      WHEN 1: REM greyscale
        IF (lj_s% AND &70) THEN
          IF lj_ht%=4 AND ((lj_s%>>4) AND 1)=0 lj_i%=0
          IF lj_ht%=8 AND ((lj_s%>>4) AND 2)=0 lj_i%=0
          IF lj_ht%=1 AND ((lj_s%>>4) AND 4)=0 lj_i%=0
        ELSE
          lj_i%=0
        ENDIF
      WHEN 2: REM colour
        IF (lj_s% AND &700) THEN
          IF lj_ht%=4 AND ((lj_s%>>8) AND 1)=0 lj_i%=0
          IF lj_ht%=8 AND ((lj_s%>>8) AND 2)=0 lj_i%=0
          IF lj_ht%=1 AND ((lj_s%>>8) AND 4)=0 lj_i%=0
        ELSE
          lj_i%=0
        ENDIF
    ENDCASE
  ENDIF

  IF lj_i%<>0 THEN
    cnfg%!CONST_cnfg_lj_options=FNstore_integer(lj_i%)
  ELSE
    PROClj_decode_options(lj_s%,lj_co%,lj_ht%)
    cnfg%!CONST_cnfg_lj_options=FNstore_integer(lj_ht%<<8 OR lj_co%)
  ENDIF

  $buff%=FNprinter_read_string_entry(prdt%,2)
  B%=buff%
  C%=2
  prnt%!CONST_prnt_name=USR(code_entry%+CONST_entry_store_string)
  lj_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 lj_s$<>"lj" $buff%=lj_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)
 */
  lj_s$=FNprinter_read_string_entry(prdt%,7)
  REM fall back to going for the default
  IF lj_s$="" lj_s$=FNmsg_0(psup%!CONST_psup_msg,"PAP")

  REM VDU: PROCftracef("initialise the best paper size we can find")
  lj_i%=0
  lj_t%=psize_head%
  WHILE lj_t%<>0 AND lj_i%=0
    IF lj_s$=FNprinter_read_string(lj_t%!CONST_psze_name) THEN lj_i%=lj_t%
    lj_t%=lj_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 lj_i%=0 THEN
    lj_t%=psize_head%
    lj_s%=0
    WHILE lj_t%<>0
      lj_nm2$=FNprinter_read_string(lj_t%!CONST_psze_name)
      WHILE lj_s%<LENlj_nm2$ AND LEFT$(lj_nm2$,lj_s%+1)=LEFT$(lj_s$,lj_s%+1)
        lj_s%+=1
        lj_i%=lj_t%
      ENDWHILE
      lj_t%=lj_t%!CONST_psze_next
    ENDWHILE
    PROCerror_warning(FNmsg_3(FNlj_host_desc,"WA11",lj_s$,FNprinter_read_string(lj_i%!CONST_psze_name),$prnt%!CONST_prnt_name))
  ENDIF
  prnt%!CONST_prnt_psze=lj_i%

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

  REM VDU: PROCftracef("PROClj_m4 done")
ENDPROC

DEF PROClj_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("lj_ensure_resource_file("+resource$+disc$+")")
  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 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(FNlj_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(FNlj_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 PROClj_m5
  REM cache any palette files that are used by lj printers and ensure
  REM that the relevant PDumper modules are loaded
  LOCAL lj_prnt%,lj_cnfg%,lj_graphics_prdt%,lj_pal$
  REM VDU: PROCftracef("PROClj_m5")
  lj_prnt%=prnt%
  WHILE lj_prnt%>0
    IF lj_prnt%!CONST_prnt_psup=psup% THEN
      REM got a printer in our class - cache the palette file
      lj_cnfg%=lj_prnt%!CONST_prnt_cnfg
      lj_graphics_prdt%=!lj_cnfg%!CONST_cnfg_lj_graphics
      REM bit 23 of palette no. flags whether already ensured or not
      lj_pal$=STR$(FNprinter_read_integer_entry(lj_graphics_prdt%,2) AND &7FFFFF)
      PROClj_ensure_resource_file("Resources.Printers.Palettes."+lj_pal$,"Printers:Palettes."+lj_pal$,lj_graphics_prdt%)

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

DEF PROClj_m6
  REM do whatever is necessary to prime the specified printer
  LOCAL lj_s$,lj_t$,lj_i%,lj_j%,xres%,yres%,halftone%,ptr%,pal%,dmp$,inf%,strip%,graphics_prdt%,text_prdt%
  LOCAL format_print%,local_pl%,local_pr%,local_pb%,local_pt%,local_ph%,local_A%,local_B%,local_G%,local_B$,B%,C%
  LOCAL flags%,newblock%,i%,a$,s%
  REM VDU: PROCftracef("PROClj_m6")
  REM 7 is the magic number for the dumper driver
  IF(lj_i% AND 1)=0 SYS"XPDriver_SelectDriver",7
  lj_s$=FNprinter_read_string(prnt%!CONST_prnt_name)
  IF lj_s$="" THEN
    lj_s$=$prnt%!CONST_prnt_type
    IF LEN lj_s$>20 THEN
      lj_i%=LEN lj_s$
      WHILE MID$(lj_s$,lj_i%,1)<>" " AND lj_i%>0
        lj_i%-=1
      ENDWHILE
      IF lj_i% lj_s$=LEFT$(lj_s$,lj_i%-1)ELSE lj_s$=LEFT$(lj_s$,20)
    ENDIF
  ENDIF
  graphics_prdt%=!cnfg%!CONST_cnfg_lj_graphics
  xres%=FNprinter_read_integer_entry(graphics_prdt%,4)
  yres%=FNprinter_read_integer_entry(graphics_prdt%,5)
  halftone%=(!cnfg%!CONST_cnfg_lj_options AND &FF00)>>8
  strip%=!cnfg%!CONST_cnfg_lj_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,lj_s$,xres%/halftone%,yres%/halftone% TO ptr%;lj_i%
  ELSE
    SYS"XPDriver_SetInfo",,xres%,yres%,0,lj_s$,xres%/halftone%,yres%/halftone% TO ptr%;lj_i%
  ENDIF
  IF (lj_i% AND 1) AND (ptr%<>0) THEN
    lj_s$="": ptr%+=4
    WHILE ?ptr%: lj_s$+=CHR$ ?ptr%: ptr%+=1: ENDWHILE
    ERROR CONST_error_ok,lj_s$
    ENDPROC
  ENDIF

  REM bit 23 of palette no. flags whether already ensured or not
  lj_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(FNlj_host_desc,"FA5")
  $pal%="Resources:$.Resources.Printers.Palettes."+lj_s$
  inf%=USR(code_entry%+CONST_entry_heap_claim)
  IFinf%=0 ERROR CONST_error_fatal, FNmsg_0(FNlj_host_desc,"FA5")
  $inf%=FNprinter_read_string_entry(graphics_prdt%,6)
  strip%=!cnfg%!CONST_cnfg_lj_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
   lj_i%=FNprinter_read_integer_entry(graphics_prdt%,1)
   lj_i%=FNprinter_read_integer_entry(lj_i%,1)
   SYS"XPDriver_MiscOp",&80000002,lj_i% TO ptr%;lj_i%
   IF(lj_i%AND1)=0 IF ptr%<>&80000002 IF(ptr% AND (1<<5))=0 strip%=3
  ENDIF
/*  REM this may be necessary, if multiple palettes for one printer */
  PROClj_ensure_resource_file("Resources.Printers.Palettes."+lj_s$,"Printers:Palettes."+lj_s$,graphics_prdt%)

  REM Module name:
  lj_s$=FNprinter_read_string_entry(FNprinter_read_integer_entry(graphics_prdt%,1),2)
  dmp$="RMLoad Printers:PDumpers."+lj_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_lj_pass_per_line=4 ELSE inf%?CONST_lj_pass_per_line=1

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

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

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

  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(FNlj_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"
  lj_i%=FNprinter_read_integer_entry(prdt%,6): REM point to the chars PRDT block
  IF lj_i% THEN
    lj_i%=lj_i%!CONST_prdt_1st
    WHILE lj_i%
      IF lj_i%?CONST_char_char=ASC"" THEN
        lj_s$=FNlj_hex2(ASC"")+FNlj_hex2(lj_i%?CONST_char_len)
        ptr%=lj_i%+CONST_char_trans
        lj_i%=lj_i%?CONST_char_len
        WHILE lj_i%
          lj_s$+=FNlj_hex2(?ptr%)
          ptr%+=1
          lj_i%-=1
        ENDWHILE
        SYS"OS_CLI","Set PDriver$TextChars1 "+lj_s$
      ELSE
        lj_i%=lj_i%!CONST_char_next
      ENDIF
    ENDWHILE
  ENDIF
  text_prdt%=!cnfg%!CONST_cnfg_lj_text
  lj_i%=prnt%!CONST_prnt_psze
  lj_s$=$lj_i%!CONST_psze_name
  lj_j%=0
  WHILE MID$(lj_s$,lj_j%,1)<>" " AND lj_j%<=LEN lj_s$
    lj_j%+=1
  ENDWHILE
  lj_t$="PT_"+LEFT$(lj_s$,lj_j%-1)
  lj_s$=FNmsg_0(psup%!CONST_psup_msg,lj_t$)
  /* Change here from RJW. If it fails to lookup, then don't send anything! */
  /* IF lj_s$=lj_t$ lj_s$=FNmsg_0(psup%!CONST_psup_msg,"PT_A4") */
  IF lj_s$=lj_t$ lj_s$=""
  lj_t$=FNlj_feed_strings+FNlj_bin_strings
  SYS"OS_CLI","Set PDumperLJ$Extra "+FNungstrans(lj_t$+lj_s$)
  format_print%=(!cnfg%!CONST_cnfg_lj_flags AND 8)>>3
  local_pl%=lj_i%!CONST_psze_lmargin
  local_pr%=lj_i%!CONST_psze_rmargin
  local_pb%=lj_i%!CONST_psze_bmargin
  local_pt%=lj_i%!CONST_psze_tmargin
  local_ph%=lj_i%!CONST_psze_pheight
  IF format_print%=0 THEN
    local_yt%=0
    WHILE local_yt%*12000<local_ph%-local_pt%
      local_yt%+=1
    ENDWHILE
    local_pt%=local_ph%-local_yt%*12000: REM 72000 DIV 6
    local_B%=(local_pr%-local_pl%)*10 DIV 72000
    local_A%=(local_pt%-local_pb%)*6 DIV 72000
  ELSE
    local_yt%=0
    WHILE local_yt%*9000<local_pl%
      local_yt%+=1
    ENDWHILE
    local_pl%=local_yt%*9000: REM 72000 DIV 8
    local_B%=((local_pt%-local_pb%)*16.66 DIV 72000 - 1)DIV 2
    local_A%=(local_pr%-local_pl%)*8 DIV 72000
  ENDIF
  IF !cnfg%!CONST_cnfg_lj_flags AND %1000 local_G%=2 ELSE local_G%=0
  lj_t$="-Ph "+STR$ local_A%+" -Pw "+STR$ local_B%+" -Mt "+STR$ lj_i%!CONST_psze_ttop
  lj_t$+=" -Mb "+STR$ lj_i%!CONST_psze_tbottom+" -Ml "+STR$ lj_i%!CONST_psze_tleft
  lj_t$+=" -Mr "+STR$ lj_i%!CONST_psze_tright+" -Th "+STR$ local_G%+" -Nl |<10>|<13>"
  local_B$=FNungstrans(FNungstrans(FNlj_font(0)))
  IF local_B$<>"" lj_t$+=" -Rs "+local_B$
  local_B$=FNungstrans(FNungstrans(FNlj_font(2)))
  IF local_B$<>"" lj_t$+=" -Cd "+local_B$
  SYS"OS_CLI","Set PDriver$TextPage "+lj_t$
  REM VDU: PROCftracef("PROClj_m6 done")
ENDPROC

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

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

DEF PROClj_p6
  LOCAL wind%,dummy%
  REM mouseclick on the configure window
  REM VDU: PROCftracef("PROClj_p6")
  CASE xbuff%!8 OF
    WHEN 2: REM menu
      CASE xbuff%!16 OF
        WHEN 20: PROClj_menu("ME1",TRUE,TRUE)
        WHEN 18: PROClj_menu("ME2",TRUE,TRUE)
        WHEN  4: PROClj_menu("ME3",TRUE,TRUE)
        WHEN 14: PROClj_menu("ME4",TRUE,TRUE)
        WHEN 23: PROClj_menu("ME5",TRUE,TRUE)
        WHEN 26: PROClj_menu("MP1",TRUE,TRUE)
        WHEN 36: PROClj_menu("ME6",TRUE,TRUE)
      ENDCASE
    WHEN 4: REM select
      CASE xbuff%!16 OF
        WHEN 24
          wind%=xbuff%!12
          PROClj_save_configuration(wind%)
          !xbuff%=wind%
          SYS"Wimp_CloseWindow",,xbuff%
        WHEN 20: PROClj_menu("ME1",TRUE,TRUE)
        WHEN 18: PROClj_menu("ME2",TRUE,TRUE)
        WHEN  4: PROClj_menu("ME3",TRUE,TRUE)
        WHEN 14: PROClj_menu("ME4",TRUE,TRUE)
        WHEN 23: PROClj_menu("ME5",TRUE,TRUE)
        WHEN 26: PROClj_menu("MP1",TRUE,TRUE)
        WHEN 36: PROClj_menu("ME6",TRUE,TRUE)
        WHEN 30
          !xbuff%=xbuff%!12
          SYS"Wimp_CloseWindow",,xbuff%
        WHEN 33
          dummy%=FNexternal_config_app(prnt%)
      ENDCASE
    WHEN 1: REM adjust
      CASE xbuff%!16 OF
        WHEN 24
          wind%=xbuff%!12
          PROClj_save_configuration(wind%)
        WHEN 33
          dummy%=FNexternal_config_app(prnt%)
      ENDCASE
  ENDCASE
ENDPROC

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

      ENDPROC
    ENDIF

    lj_i%=lj_i%!CONST_wind_next
  ENDWHILE
ENDPROC

DEF PROClj_p9
  LOCAL adjust%,wind%,icon%,ptr%,xres%,yres%
/*
 * 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("PROClj_p9")
  wind%=FNprinter_find_window(prnt%,"configure")
  adjust%=FNwas_adjust_used
  CASE lj_menu_chsn$ OF
    WHEN "ME1": icon%=3
    WHEN "ME2": icon%=17
    WHEN "ME3": icon%=15
    WHEN "ME4": icon%=13
    WHEN "ME5": icon%=22
    WHEN "MP1": icon%=25
    WHEN "ME6": icon%=35
  ENDCASE
  ptr%=lj_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 lj_menu_chsn$="ME1" THEN
    REM if the resolution changes, we may have to change the quality as well
    lj_j%=prdt%!20
    lj_s$=FNicon_read(wind%,3)
    WHILE lj_j%
      lj_k%=!lj_j%!CONST_lstd_1st
      IF (lj_s$=FNmsg_2(psup%!CONST_psup_msg,"RES",STR$ !lj_k%!20,STR$ !lj_k%!24)) OR \
         (lj_s$=$(lj_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
 */
        lj_s$=FNicon_read(wind%,15): lj_i%=INSTR(lj_s$,",")
        CASE LEFT$(lj_s$,lj_i%-1)OF
          WHEN FNmsg_0(psup%!CONST_psup_msg,"CO1"):  lj_j%=1
          WHEN FNmsg_0(psup%!CONST_psup_msg,"CO1s"): lj_j%=1
          WHEN FNmsg_0(psup%!CONST_psup_msg,"CO2"):  lj_j%=2
          WHEN FNmsg_0(psup%!CONST_psup_msg,"CO4"):  lj_j%=4
          WHEN FNmsg_0(psup%!CONST_psup_msg,"CO5"):  lj_j%=5
          WHEN FNmsg_0(psup%!CONST_psup_msg,"CO5s"): lj_j%=5
          OTHERWISE:                                 lj_j%=0
        ENDCASE
        lj_s$=MID$(lj_s$,lj_i%+2)
        CASE lj_s$ OF
          WHEN FNmsg_0(psup%!CONST_psup_msg,"HT8"):  lj_i%=8
          WHEN FNmsg_0(psup%!CONST_psup_msg,"HT8s"): lj_i%=8
          WHEN FNmsg_0(psup%!CONST_psup_msg,"HT1"):  lj_i%=1
          WHEN FNmsg_0(psup%!CONST_psup_msg,"HT1s"): lj_i%=1
          OTHERWISE:                                 lj_i%=4
        ENDCASE
        lj_k%=FNlj_get_quality_options(lj_k%)
        IF(lj_k% AND (7<<(lj_j%*4)))=0 lj_j%=-1
        IF lj_j%<>-1 THEN
          lj_j%=lj_k%>>lj_j%*4
          CASE lj_i% OF
            WHEN 4: IF(lj_j% AND 1)=0 lj_i%=-1
            WHEN 8: IF(lj_j% AND 2)=0 lj_i%=-1
            WHEN 1: IF(lj_j% AND 4)=0 lj_i%=-1
          ENDCASE
        ENDIF
        IF lj_j%=-1 OR lj_i%=-1 THEN
          PROClj_decode_options(lj_k%,lj_j%,lj_i%)
          PROCicon_write(wind%,15,FNlj_qual_name(lj_j% + (lj_i% << 8)))
        ENDIF
        lj_j%=0
      ELSE
        lj_j%=!lj_j%
      ENDIF
    ENDWHILE
  ENDIF
  IF adjust% THEN
    SYS"Wimp_GetPointerInfo",,xbuff%
    PROClj_menu(lj_menu_chsn$,FALSE,FALSE)
  ENDIF
ENDPROC

DEF PROClj_p17
  LOCAL wind%,lj_s$,lj_t$
  REM VDU: PROCftracef("PROClj_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"
              lj_s$=STR$ xbuff%!36
              CASE xbuff%!36 OF
                WHEN 8,11,12
                  IF FNicon_set(xbuff%!32,xbuff%!36)lj_s$+="b" ELSE lj_s$+="a"
              ENDCASE
              lj_t$=FNmsg_0(psup%!CONST_psup_msg,"CON"+lj_s$)
              IF lj_t$="CON"+lj_s$ lj_t$=FNmsg_0(psup%!CONST_psup_msg,"CON")
              PROCinteractive_help(lj_t$)
          ENDCASE
          wind%=0
        ELSE
          wind%=wind%!CONST_wind_next
          IF wind%=0 PROCinteractive_help(FNmsg_0(psup%!CONST_psup_msg,"H"+lj_menu_chsn$))
        ENDIF
      ENDWHILE
    WHEN &8014B
      /*PrintInterrogate*/
      CASE xbuff%!20 OF
      WHEN 0
        IF prnt% AND xbuff%!24=prnt% THEN PROClj_interrogate0
      ENDCASE
  ENDCASE
ENDPROC

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

DEF PROClj_save_configuration(window%)
  LOCAL lj_i%,lj_j%,lj_k%,lj_s$,B%,C%,lj_x%,lj_t$
  REM VDU: PROCftracef("PROClj_save_configuration_window")
  prdt%=FNprinter_find_prdata_entry(psup%,FNicon_read(window%,6))
  PROCfree_structure(prnt%!CONST_prnt_name)
  $buff%=FNicon_read(window%,27)
  B%=buff%
  C%=2
  prnt%!CONST_prnt_name=USR(code_entry%+CONST_entry_store_string)
  lj_i%=cnfg%
  FOR lj_j%=1 TO CONST_cnfg_lj_MAX/4
    PROCfree_structure(!lj_i%)
    !lj_i%=0
    lj_i%+=4
  NEXT
  lj_j%=0
  IF FNprinter_read_string_entry(prdt%,13)="" THEN
    IF FNicon_read(window%,17)=FNmsg_0(psup%!CONST_psup_msg,"PF1")lj_j%+=1
  ELSE
    lj_n%=FNlj_binfeed_save("Feeds",FNprinter_read_string_entry(prdt%,13),FNicon_read(window%,17))
    lj_j%=(lj_n% AND 1) + ((lj_n%>>1)<<16)
  ENDIF
  IF FNprinter_read_string_entry(prdt%,14)<>"" THEN
    lj_n%=FNlj_binfeed_save("Bins",FNprinter_read_string_entry(prdt%,14),FNicon_read(window%,35))
    lj_j%+=lj_n%<<21
  ENDIF
  IF FNicon_set(window%,8)lj_j%+=2
  IF FNicon_set(window%,11)lj_j%+=4
  IF FNicon_read(window%,13)=FNmsg_0(psup%!CONST_psup_msg,"PO1")lj_j%+=8
  CASE FNicon_read(window%,22)OF
    WHEN FNmsg_0(psup%!CONST_psup_msg,"CC1"): lj_j%+=1<<8
    WHEN FNmsg_0(psup%!CONST_psup_msg,"CC2"): lj_j%+=1<<9
  ENDCASE
  cnfg%!CONST_cnfg_lj_flags=FNstore_integer(lj_j%)
  REM portrait mode is no-highlights entry
  REM landscape mode is drafts entry
  IF lj_j% AND 8 THEN
    lj_j%=FNprinter_read_list_integer_entry(prdt%,5,2,1)
  ELSE
    lj_j%=FNprinter_read_list_integer_entry(prdt%,5,1,1)
  ENDIF
  IF lj_j% THEN
    B%=CONST_ident_POTR
    C%=4
    cnfg%!CONST_cnfg_lj_text=USR(code_entry%+CONST_entry_heap_claim)
    IF cnfg%!CONST_cnfg_lj_text=0 ERROR CONST_error_fatal, FNmsg_0(FNlj_host_desc,"FA5")
    !cnfg%!CONST_cnfg_lj_text=lj_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
  lj_j%=prdt%!20: REM printer name is 8, short name is 12, sprite name is 16, resolution is 20
  lj_s$=FNicon_read(window%,3)
  WHILE lj_j%
    lj_k%=!lj_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 (lj_s$=FNmsg_2(psup%!CONST_psup_msg,"RES",STR$ !lj_k%!20,STR$ !lj_k%!24)) OR \
       (lj_s$=$(lj_k%!36)) THEN
      lj_j%=0
    ELSE
      lj_j%=!lj_j%
    ENDIF
  ENDWHILE
  B%=CONST_ident_POTR
  C%=4
  cnfg%!CONST_cnfg_lj_graphics=USR(code_entry%+CONST_entry_heap_claim)
  IF cnfg%!CONST_cnfg_lj_graphics=0 ERROR CONST_error_fatal, FNmsg_0(FNlj_host_desc,"FA5")
  !cnfg%!CONST_cnfg_lj_graphics=lj_k%
  lj_s$=FNicon_read(window%,15)
  lj_i%=INSTR(lj_s$,",")
  CASE LEFT$(lj_s$,lj_i%-1)OF
    WHEN FNmsg_0(psup%!CONST_psup_msg,"CO1"):  lj_j%=1
    WHEN FNmsg_0(psup%!CONST_psup_msg,"CO1s"): lj_j%=1
    WHEN FNmsg_0(psup%!CONST_psup_msg,"CO2"):  lj_j%=2
    WHEN FNmsg_0(psup%!CONST_psup_msg,"CO4"):  lj_j%=4
    WHEN FNmsg_0(psup%!CONST_psup_msg,"CO5"):  lj_j%=5
    WHEN FNmsg_0(psup%!CONST_psup_msg,"CO5s"): lj_j%=5
    OTHERWISE: lj_j%=0
  ENDCASE
  lj_s$=MID$(lj_s$,lj_i%+2)
  CASE lj_s$ OF
    WHEN FNmsg_0(psup%!CONST_psup_msg,"HT8"):  lj_i%=8
    WHEN FNmsg_0(psup%!CONST_psup_msg,"HT8s"): lj_i%=8
    WHEN FNmsg_0(psup%!CONST_psup_msg,"HT1"):  lj_i%=1
    WHEN FNmsg_0(psup%!CONST_psup_msg,"HT1s"): lj_i%=1
    OTHERWISE:                                 lj_i%=4
  ENDCASE
  cnfg%!CONST_cnfg_lj_options=FNstore_integer((lj_i%<<8)+lj_j%)
  lj_j%=prnt%!CONST_prnt_psze
  lj_s$=FNicon_read(window%,25)
  IF $lj_j%!CONST_psze_name<>lj_s$ THEN
    lj_i%=psize_head%
    WHILE lj_i%
      IF $lj_i%!CONST_psze_name=lj_s$ THEN
        prnt%!CONST_prnt_psze=lj_i%
        lj_i%=0
      ELSE
        lj_i%=!lj_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): REM don't do this (calls into overlay). JRC 12 Feb '92
  ENDIF
ENDPROC

DEF FNlj_res(cnfg%)
  LOCAL xres%,yres%,graphics_prdt%,nm$
  REM VDU: PROCftracef("FNlj_res")
  graphics_prdt%=!cnfg%!CONST_cnfg_lj_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 FNlj_qual_name(lj_i%)
  LOCAL lj_s$,lj_t$
  IF LJQ$ = "S" THEN
    lj_s$=FNmsg_0(psup%!CONST_psup_msg,"CO"+STR$(lj_i% AND &FF)+"s")
    lj_t$=FNmsg_0(psup%!CONST_psup_msg,"HT"+STR$((lj_i% AND &FF00)>>8)+"s")
  ELSE
    lj_s$=FNmsg_0(psup%!CONST_psup_msg,"CO"+STR$(lj_i% AND &FF))
    lj_t$=FNmsg_0(psup%!CONST_psup_msg,"HT"+STR$((lj_i% AND &FF00)>>8))
  ENDIF
=lj_s$+", "+lj_t$

DEF FNlj_qual(cnfg%)
  LOCAL lj_i%
  REM VDU: PROCftracef("FNlj_qual")
  lj_i%=!cnfg%!CONST_cnfg_lj_options
=FNlj_qual_name(lj_i%)

DEF FNlj_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 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 LJQ$ = "S" s%=s% AND &700070
=s%

REM If LJQ$ = "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 PROClj_decode_options(option%,RETURN strip%,RETURN tone%)
  REM VDU: PROCftracef("PROClj_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 LJQ$ = "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 PROClj_menu(top$,rebuild%,iconpos%)
  LOCAL wind%,lj_ix%,lj_iy%,lj_i%,lj_x%,lj_j%,lj_k%,xres%,yres%,indt%,nm$
  REM VDU: PROCftracef("PROClj_menu")
  IF rebuild% THEN
    lj_menu_xpos%=xbuff%!0-64
    lj_menu_ypos%=xbuff%!4
  ENDIF
  IF iconpos% THEN
    !buff%=xbuff%!12
    buff%!4=xbuff%!16
    SYS"Wimp_GetIconState",,buff%
    lj_ix%=buff%!16
    lj_iy%=buff%!20
    SYS"Wimp_GetWindowState",,buff%
    lj_menu_xpos%=buff%!20+buff%!4+lj_ix%+2
    lj_menu_ypos%=buff%!24+buff%!16+lj_iy%-2
  ENDIF
  wind%=FNprinter_find_window(prnt%,"configure")
  lj_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(lj_menu%,FNmsg_0(psup%!CONST_psup_msg,"ME1"))
      indt%=(lj_menu%!28 AND &100)<>0
      REM get the resolution strings for this printer
      lj_j%=prdt%!20
      lj_i%=0
      lj_x%=0
      WHILE lj_j%
        lj_k%=!lj_j%!CONST_lstd_1st
        xres%=FNprinter_read_integer_entry(lj_k%,4)
        yres%=FNprinter_read_integer_entry(lj_k%,5)
        nm$=FNprinter_read_string_entry(lj_k%,8)
        IF nm$<>"" THEN
          PROCmenu_item(lj_menu%,lj_i%,nm$,indt%)
        ELSE
          PROCmenu_item(lj_menu%,lj_i%,FNmsg_2(psup%!CONST_psup_msg,"RES",STR$ xres%,STR$ yres%),indt%)
        ENDIF
        lj_i%+=1
        lj_j%=!lj_j%
      ENDWHILE
      PROCmenu_tick_match(lj_menu%,FNicon_read(wind%,3))
    WHEN "ME2"
      IF FNprinter_read_string_entry(prdt%,13)="" THEN
        PROCmenu_create(lj_menu%,FNmsg_0(psup%!CONST_psup_msg,"ME2"))
        PROCmenu_tick_match(lj_menu%,FNicon_read(wind%,17))
      ELSE
        PROClj_binfeed_menu(lj_menu%,"ME2b","Feeds",FNprinter_read_string_entry(prdt%,13))
        PROCmenu_tick_match(lj_menu%,FNicon_read(wind%,17))
      ENDIF
    WHEN "ME3"
      PROCmenu_create(lj_menu%,FNmsg_0(psup%!CONST_psup_msg,"ME3"))
      REM need to find the right graphics entry for the current resolution
      lj_j%=prdt%!20: REM point to first record for this list
      WHILE lj_j%
        lj_k%=!lj_j%!CONST_lstd_1st
        IF (FNicon_read(wind%,3)=FNmsg_2(psup%!CONST_psup_msg,"RES",STR$ !lj_k%!20,STR$ !lj_k%!24)) OR \
           (FNicon_read(wind%,3)=$(lj_k%!36)) THEN
          REM ok - found the graphics entry, now get the options word
          lj_j%=FNlj_get_quality_options(lj_k%)
          lj_i%=0
          lj_x%=0
          IF lj_j% AND &000007 PROClj_menu_quality(lj_menu%,lj_i%,FNmsg_0(psup%!CONST_psup_msg,"CO0"),lj_j%)
          IF lj_j% AND &000070 THEN
            IF LJQ$="S" THEN
              PROClj_menu_quality(lj_menu%,lj_i%,FNmsg_0(psup%!CONST_psup_msg,"CO1s"),lj_j%>>4)
            ELSE
              PROClj_menu_quality(lj_menu%,lj_i%,FNmsg_0(psup%!CONST_psup_msg,"CO1"),lj_j%>>4)
            ENDIF
          ENDIF
          IF lj_j% AND &000700 PROClj_menu_quality(lj_menu%,lj_i%,FNmsg_0(psup%!CONST_psup_msg,"CO2"),lj_j%>>8)
          IF lj_j% AND &070000 PROClj_menu_quality(lj_menu%,lj_i%,FNmsg_0(psup%!CONST_psup_msg,"CO4"),lj_j%>>16)
          IF lj_j% AND &700000 THEN
            IF LJQ$="S" THEN
              PROClj_menu_quality(lj_menu%,lj_i%,FNmsg_0(psup%!CONST_psup_msg,"CO5s"),lj_j%>>20)
            ELSE
              PROClj_menu_quality(lj_menu%,lj_i%,FNmsg_0(psup%!CONST_psup_msg,"CO5"),lj_j%>>20)
            ENDIF
          ENDIF
          lj_j%=0
        ELSE
          lj_j%=!lj_j%
        ENDIF
      ENDWHILE
      PROCmenu_tick_match(lj_menu%,FNicon_read(wind%,15))
    WHEN "ME4"
      IFFNprinter_read_list_integer_entry(prdt%,5,2,1)<>0 THEN
        PROCmenu_create(lj_menu%,FNmsg_0(psup%!CONST_psup_msg,"ME4a"))
      ELSE
        PROCmenu_create(lj_menu%,FNmsg_0(psup%!CONST_psup_msg,"ME4b"))
      ENDIF
      PROCmenu_tick_match(lj_menu%,FNicon_read(wind%,13))
    WHEN "ME5"
      PROCmenu_create(lj_menu%,FNmsg_0(psup%!CONST_psup_msg,"ME5"))
      PROCmenu_tick_match(lj_menu%,FNicon_read(wind%,22))
    WHEN "ME6"
      PROClj_binfeed_menu(lj_menu%,"ME6","Bins",FNprinter_read_string_entry(prdt%,14))
      PROCmenu_tick_match(lj_menu%,FNicon_read(wind%,35))
    WHEN "MP1"
      PROCcreate_paper_menu(lj_menu%,wind%,25)
  ENDCASE
  PROCdisplay_menu(prnt%,lj_menu%,lj_menu_xpos%,lj_menu_ypos%)
ENDPROC

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

DEF FNlj_hex2(v%)
  REM VDU: PROCftracef("PROClj_hex2")
=RIGHT$("00"+STR$~v%,2)

REM text printing code

DEF PROClj_m8
  LOCAL lj_r%,queu%,tpub%,tprv%,text_prdt%
  REM VDU: PROCftracef("PROClj_m8")
  text_prdt%=!cnfg%!CONST_cnfg_lj_text
  lj_r%=!xbuff%
  queu%=xbuff%!4
  tpub%=queu%!CONST_queu_tpub
  tprv%=queu%!CONST_queu_tprv
  CASE lj_r% OF
    WHEN  -1: PROClj_1
    WHEN  -2: PROClj_2
    WHEN  -4: PROClj_4
    WHEN  -6: PROClj_6
    WHEN  -7: PROClj_7
    WHEN  -9: PROClj_9
    WHEN -10: PROClj_10
    WHEN -11: PROClj_11
    WHEN -12: PROClj_12
    WHEN -13: PROClj_13
    WHEN -15: PROClj_15
    WHEN -16: PROClj_16
    WHEN -17: PROClj_17
    WHEN -18: PROClj_18
    WHEN -19: PROClj_19
  ENDCASE
ENDPROC

DEF PROClj_1
/*  REM only called if we aren't printing an LJ data file */
  LOCAL lj_i%,lj_i$,lj_j%,B%,C%
  REM VDU: PROCftracef("PROClj_1")
  B%=CONST_ident_TPRV
  C%=CONST_tprv_lj_MAX
  tprv%=USR(code_entry%+CONST_entry_heap_claim)
  IF tprv%=0 ERROR CONST_error_fatal, FNmsg_0(FNlj_host_desc,"FA5")
  queu%!CONST_queu_tprv=tprv%
  FOR lj_i%=0 TO CONST_tprv_lj_MAX-4
    tprv%!lj_i%=0
  NEXT
  lj_j%=!cnfg%!CONST_cnfg_lj_flags
  tpub%!CONST_tpub_cc_print=(lj_j% AND &FF00)>>8
  IF lj_j% AND 4 THEN
    tpub%!CONST_tpub_number_print=TRUE
    tprv%!CONST_tprv_lj_xt=6
  ELSE
    tprv%!CONST_tprv_lj_xt=0
  ENDIF
  IF lj_j% AND 2 tpub%!CONST_tpub_title_print=TRUE
  lj_i$=FNprinter_read_string_entry(text_prdt%,6)
  B%=A%!CONST_interface_scratch
  $B%=lj_i$
  C%=5
  D%=LEN lj_i$
  tpub%!CONST_tpub_line_epilogue=USR(code_entry%+CONST_entry_store_string)
  REM set the pointer to the char translation list
  lj_j%=FNprinter_read_integer_entry(prdt%,6): REM point to the PRDT block
  IF lj_j% lj_j%=lj_j%!CONST_prdt_1st
  queu%!CONST_queu_char=lj_j%
ENDPROC

DEF PROClj_2
  REM output job start strings
  LOCAL format_print%,lj_pl%,lj_pr%,lj_pb%,lj_pt%,lj_ph%,psze%,lj_yt%
  LOCAL lj_i%, lj_j%, lj_s$, lj_t$
  REM VDU: PROCftracef("PROClj_2")
  REM first reset the printer
  BPUT#xbuff%!8,CHR$ 27+"E";
  REM set paper feed ...
  lj_s$=FNlj_feed_strings
  IF lj_s$<>"" THEN
    SYS "OS_GSTrans",lj_s$,buff%,256 TO ,,lj_j%
    lj_i%=0
    WHILE lj_j%: BPUT#xbuff%!8,buff%?lj_i%: lj_i%+=1: lj_j%-=1: ENDWHILE
  ENDIF
  REM set output bin ...
  lj_s$=FNlj_bin_strings
  IF lj_s$<>"" THEN
    SYS "OS_GSTrans",lj_s$,buff%,256 TO ,,lj_j%
    lj_i%=0
    WHILE lj_j%: BPUT#xbuff%!8,buff%?lj_i%: lj_i%+=1: lj_j%-=1: ENDWHILE
  ENDIF
  REM set paper size ...
  lj_i%=prnt%!CONST_prnt_psze
  lj_s$=$lj_i%!CONST_psze_name
  lj_j%=0
  WHILE MID$(lj_s$,lj_j%,1)<>" " AND lj_j%<=LEN lj_s$
    lj_j%+=1
  ENDWHILE
  lj_t$="PT_"+LEFT$(lj_s$,lj_j%-1)
  lj_s$=FNmsg_0(psup%!CONST_psup_msg,lj_t$)
  IF lj_s$=lj_t$ lj_s$=FNmsg_0(psup%!CONST_psup_msg,"PT_A4")
  IF lj_s$<>"" THEN
    SYS "OS_GSTrans",lj_s$,buff%,256 TO ,,lj_j%
    lj_i%=0
    WHILE lj_j%: BPUT#xbuff%!8,buff%?lj_i%: lj_i%+=1: lj_j%-=1: ENDWHILE
  ENDIF
  format_print%=(!cnfg%!CONST_cnfg_lj_flags AND 8)>>3
  psze%=prnt%!CONST_prnt_psze
  lj_pl%=psze%!CONST_psze_lmargin
  lj_pr%=psze%!CONST_psze_rmargin
  lj_pb%=psze%!CONST_psze_bmargin
  lj_pt%=psze%!CONST_psze_tmargin
  lj_ph%=psze%!CONST_psze_pheight
  IF format_print%=0 THEN
    REM portrait
    lj_yt%=0
    WHILE lj_yt%*12000<lj_ph%-lj_pt%
      lj_yt%+=1
    ENDWHILE
    lj_pt%=lj_ph%-lj_yt%*12000: REM 72000 DIV 6
    lj_yt%+=psze%!CONST_psze_ttop
    tpub%!CONST_tpub_xc=(lj_pr%-lj_pl%)*10 DIV 72000
    tprv%!CONST_tprv_lj_yc=(lj_pt%-lj_pb%)*6 DIV 72000
  ELSE
    lj_yt%=0
    WHILE lj_yt%*9000<lj_pl%
      lj_yt%+=1
    ENDWHILE
    lj_pl%=lj_yt%*9000: REM 72000 DIV 8
    lj_yt%+=psze%!CONST_psze_ttop
    tpub%!CONST_tpub_xc=((lj_pt%-lj_pb%)*16.66 DIV 72000 -1) DIV 2
    tprv%!CONST_tprv_lj_yc=(lj_pr%-lj_pl%)*8 DIV 72000
  ENDIF
  tprv%!CONST_tprv_lj_right_print=psze%!CONST_psze_tright
  tpub%!CONST_tpub_xc-=tprv%!CONST_tprv_lj_right_print
  tprv%!CONST_tprv_lj_yc-=psze%!CONST_psze_ttop+psze%!CONST_psze_tbottom
  lj_s$=FNprinter_read_string_entry(text_prdt%,7)
  IFlj_s$<>"" BPUT#xbuff%!8,lj_s$;
  REM finally, set the number of lines per page
  BPUT#xbuff%!8,CHR$ 27+"&l"+STR$(tprv%!CONST_tprv_lj_yc+lj_yt%)+"F";
  tprv%!CONST_tprv_lj_xw=tpub%!CONST_tpub_xc
  tprv%!CONST_tprv_lj_left_print=psze%!CONST_psze_tleft
  tprv%!CONST_tprv_lj_left_ruler=0
  tprv%!CONST_tprv_lj_mt=lj_yt%
  tpub%!CONST_tpub_line_max=tprv%!CONST_tprv_lj_yc
  tprv%!CONST_tprv_lj_xl=tprv%!CONST_tprv_lj_left_print
  IF tpub%!CONST_tpub_number_print tprv%!CONST_tprv_lj_xl+=6
ENDPROC

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

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

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

DEF PROClj_9
  LOCAL changed_bits%,clr_bits%,set_bits%,bit%,lj_b$
  REM VDU: PROCftracef("PROClj_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% lj_b$+=FNlj_style_off(bit%)
      IF set_bits% AND 1<<bit% lj_b$+=FNlj_style_on(bit%)
    NEXT
  ENDIF
  xbuff%?8=LEN lj_b$
  $(xbuff%+9)=lj_b$
ENDPROC

DEF PROClj_10
  REM end the previous line and start a new line
  LOCAL lj_b$,wrap%,line_num$,lj_bit%
  REM VDU: PROCftracef("PROClj_10")
  tpub%!CONST_tpub_line_page+=1
  tpub%!CONST_tpub_line_doc+=1
  FOR lj_bit%=0 TO 5
    IF tpub%!CONST_tpub_style_bits AND 1<<lj_bit% lj_b$+=FNlj_style_off(lj_bit%)
  NEXT
  REM lj_b$+=FNprinter_read_string_entry(text_prdt%,6)
  lj_b$+=CHR$ 27+"&a"
  lj_b$+=STR$(tprv%!CONST_tprv_lj_left_print+tprv%!CONST_tprv_lj_left_ruler+tprv%!CONST_tprv_lj_col*(tprv%!CONST_tprv_lj_xw+1))+"C"
  wrap%=(tpub%!CONST_tpub_cpos>=tpub%!CONST_tpub_xc)
  IF tpub%!CONST_tpub_number_print THEN
    REM print line number unless wrapped line
    lj_b$+=FNlj_font(0)
    IF wrap% THEN
      tpub%!CONST_tpub_line_doc-=1
      lj_b$+=STRING$(6," ")
    ELSE
      line_num$=STR$ tpub%!CONST_tpub_line_doc
      lj_b$+=STRING$(5-LEN line_num$," ")+line_num$+" "
    ENDIF
    lj_b$+=FNlj_font(tpub%!CONST_tpub_font_num)
    tpub%!CONST_tpub_cpos=6
  ELSE
    tpub%!CONST_tpub_cpos=0
  ENDIF
  IF wrap% THEN
    tpub%!CONST_tpub_cpos+=1
    lj_b$+=FNlj_style_on(0)+"|"+FNlj_style_off(0)
  ENDIF
  FOR lj_bit%=0 TO 5
    IF tpub%!CONST_tpub_style_bits AND 1<<lj_bit% lj_b$+=FNlj_style_on(lj_bit%)
  NEXT
  tpub%!CONST_tpub_cpos+=tprv%!CONST_tprv_lj_left_print+tprv%!CONST_tprv_lj_left_ruler
  xbuff%?8=LEN lj_b$
  $(xbuff%+9)=lj_b$
ENDPROC

DEF PROClj_11
  REM print a footnote number
  LOCAL lj_b$,lj_i%
  REM VDU: PROCftracef("PROClj_11")
  PROClj_10: lj_b$=FNprinter_read_string(tpub%!CONST_tpub_line_epilogue)+$(xbuff%+9)
  PROClj_10: lj_b$+=FNprinter_read_string(tpub%!CONST_tpub_line_epilogue)+$(xbuff%+9)
  lj_b$+=FNlj_style_on(4): REM superscript
  lj_b$+=FNlj_trans(RIGHT$("  "+STR$ tpub%!CONST_tpub_footnote_num,3)+STRING$(3,FNprinter_read_string_entry(text_prdt%,2)))
  lj_b$+=FNlj_style_off(4)
  xbuff%?8=LEN lj_b$
  $(xbuff%+9)=lj_b$
ENDPROC

DEF PROClj_12
  REM do bulk string translation
  LOCAL lj_b$
  REM VDU: PROCftracef("PROClj_12")
  lj_b$=FNlj_trans($(xbuff%+8))
  xbuff%?8=LEN lj_b$
  $(xbuff%+9)=lj_b$
ENDPROC

DEF PROClj_13
  REM do font change
  LOCAL lj_b$,lj_i%
  REM VDU: PROCftracef("PROClj_13")
  tpub%!CONST_tpub_font_num=xbuff%!8
  lj_i%=tprv%!CONST_tprv_lj_xl
  lj_i%+=INT((tprv%!CONST_tprv_lj_xw-tprv%!CONST_tprv_lj_xl-tprv%!CONST_tprv_lj_right_print)*FNlj_fontsize(xbuff%!8)/FNlj_fontsize(0))
  tpub%!CONST_tpub_xc=lj_i%
  IF tpub%!CONST_tpub_left_new<tpub%!CONST_tpub_xc-tprv%!CONST_tprv_lj_xl THEN
    tprv%!CONST_tprv_lj_left_ruler=tpub%!CONST_tpub_left_new
  ELSE
    tprv%!CONST_tprv_lj_left_ruler=0
  ENDIF
  IF tpub%!CONST_tpub_right_new<tpub%!CONST_tpub_xc-tprv%!CONST_tprv_lj_xl AND tpub%!CONST_tpub_right_new>tprv%!CONST_tprv_lj_left_ruler THEN
    tpub%!CONST_tpub_xc=tprv%!CONST_tprv_lj_xl+tpub%!CONST_tpub_right_new
  ENDIF
  lj_b$=FNlj_font(xbuff%!8)
  xbuff%?8=LEN lj_b$
  $(xbuff%+9)=lj_b$
ENDPROC

DEF PROClj_15
  REM end of job
  LOCAL text_prdt%,tpub%,lj_s$
  REM VDU: PROCftracef("PROClj_15")
  IF queu%!CONST_queu_type<>&FF4 THEN
    text_prdt%=!cnfg%!CONST_cnfg_lj_text
    tpub%=queu%!CONST_queu_tpub
    REM finish off the text printing
    lj_s$=FNprinter_read_string_entry(text_prdt%,8)
    IF lj_s$<>"" BPUT#xbuff%!8,lj_s$;
  ENDIF
ENDPROC

DEF PROClj_16
  REM process a tab
  LOCAL lj_b$
  REM VDU: PROCftracef("PROClj_16")
  lj_b$=CHR$ 27+"&a+"
  lj_b$+=STR$(8-((tpub%!CONST_tpub_cpos-tprv%!CONST_tprv_lj_left_print-tprv%!CONST_tprv_lj_left_ruler+1-tprv%!CONST_tprv_lj_xt)MOD 8))+"C"
  tpub%!CONST_tpub_xc+=8-((tpub%!CONST_tpub_cpos-tprv%!CONST_tprv_lj_left_print-tprv%!CONST_tprv_lj_left_ruler+1-tprv%!CONST_tprv_lj_xt)MOD 8)
  xbuff%?8=LEN lj_b$
  $(xbuff%+9)=lj_b$
ENDPROC

DEF PROClj_17
  REM do a formfeed
  REM VDU: PROCftracef("PROClj_17")
  xbuff%?8=0
ENDPROC

DEF PROClj_18
  REM change layout
  LOCAL layout_height%,layout_top%,layout_bottom%
  REM VDU: PROCftracef("PROClj_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_lj_yc THEN
    tpub%!CONST_tpub_line_max=layout_height%-layout_top%-layout_bottom%
    tprv%!CONST_tprv_lj_mt=layout_top%
  ENDIF
  xbuff%?8=0
ENDPROC

DEF PROClj_19
  REM start a new page
  LOCAL lj_b$,lj_bit%,lj_p%,lj_t$
  REM VDU: PROCftracef("PROClj_19")
  tpub%!CONST_tpub_line_page=0
  tpub%!CONST_tpub_page_num+=1
  IF((!cnfg%!CONST_cnfg_lj_flags AND 8)>>3)=0 OR (tpub%!CONST_tpub_page_num MOD 2)<>0 THEN
    tprv%!CONST_tprv_lj_col=0
  ELSE
    tprv%!CONST_tprv_lj_col=1
  ENDIF
  IF tpub%!CONST_tpub_page_num>1 THEN
    REM turn off the highlights from the previous page
    FOR lj_bit%=0 TO 5
      IF tpub%!CONST_tpub_style_bits AND 1<<lj_bit% lj_b$+=FNlj_style_off(lj_bit%)
    NEXT
  ENDIF
  REM physical formfeed only if not staying on same piece of paper
  IF tprv%!CONST_tprv_lj_col=0 AND tpub%!CONST_tpub_page_num>1 THEN
    lj_b$+=FNprinter_read_string_entry(text_prdt%,4)
  ENDIF
  lj_b$+=CHR$ 27+"&a"+STR$ tprv%!CONST_tprv_lj_mt+"R"
  IF tpub%!CONST_tpub_title_print THEN
    lj_p%=tpub%!CONST_tpub_page_num
    IF(!cnfg%!CONST_cnfg_lj_flags AND 8)>>3 THEN
      REM if landscape mode, we fit two pages per physical page
      lj_p%=(lj_p%+1)DIV 2
    ENDIF
    tpub%!CONST_tpub_line_page+=2
    IF tprv%!CONST_tprv_lj_col=0 THEN
      lj_b$+=CHR$ 27+"&a"+STR$(tprv%!CONST_tprv_lj_left_print+tprv%!CONST_tprv_lj_left_ruler)+"C"+CHR$ 14
      lj_t$=FNprinter_read_string(tpub%!CONST_tpub_name)+"   "+FNprinter_read_string(tpub%!CONST_tpub_time)
      lj_t$+="   "+FNmsg_1(psup%!CONST_psup_msg,"PAG",STR$ lj_p%)
      lj_b$+=FNlj_trans(lj_t$)+CHR$ 15
    ENDIF
    lj_b$+=FNprinter_read_string_entry(text_prdt%,6)+FNprinter_read_string_entry(text_prdt%,6)
  ENDIF
  xbuff%?8=LEN lj_b$
  $(xbuff%+9)=lj_b$
ENDPROC

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

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

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

DEF FNlj_style_on(bit%)
  REM VDU: PROCftracef("FNlj_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 FNlj_style_off(bit%)
  REM VDU: PROCftracef("FNlj_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 FNlj_font(font%)
  REM VDU: PROCftracef("FNlj_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
  REM VDU: PROCftracef("FNlj_font done")
=""

DEF FNlj_fontsize(num%)
  REM provide notional cpi sizes
  REM VDU: PROCftracef("FNlj_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
=10

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

DEF FNlj_get_feed_name(lj_dir$,lj_j%)
=FNlj_get_gen_name(lj_dir$,lj_j%,"Feeds")

DEF FNlj_get_bin_name(lj_dir$,lj_j%)
=FNlj_get_gen_name(lj_dir$,lj_j%,"Bins")

DEF FNlj_get_gen_name(lj_dir$,lj_j%,lj_t$)
=FNget_gen_name("lj",lj_dir$,lj_j%,lj_t$,buff%)

DEF FNlj_feed_strings
  LOCAL lj_s$,lj_j%
  IF FNprinter_read_string_entry(prdt%,13)<>"" THEN
    lj_j%=!cnfg%!CONST_cnfg_lj_flags
    lj_j%=(lj_j% AND 1) + ((lj_j% AND &1F0000)>>15)
    lj_s$=FNlj_gen_strings(lj_j%,"Feeds",FNprinter_read_string_entry(prdt%,13))
  ELSE
    IF !cnfg%!CONST_cnfg_lj_flags AND 1 THEN
      lj_s$=FNmsg_0(psup%!CONST_psup_msg,"MANUAL_FEED")
    ELSE
      lj_s$=FNmsg_0(psup%!CONST_psup_msg,"AUTO_FEED")
    ENDIF
  ENDIF
=lj_s$

DEF FNlj_bin_strings
  LOCAL lj_s$,lj_j%
  IF FNprinter_read_string_entry(prdt%,14)<>"" THEN
    lj_j%=!cnfg%!CONST_cnfg_lj_flags
    lj_j%=(lj_j% AND &17E00000)>>21
    lj_s$=FNlj_gen_strings(lj_j%,"Bins",FNprinter_read_string_entry(prdt%,14))
  ELSE
    lj_s$=""
  ENDIF
=lj_s$

DEF FNlj_gen_strings(lj_j%,lj_t$,lj_dir$)
=FNgen_strings("lj",lj_j%,lj_t$,lj_dir$,buff%)

DEF PROClj_binfeed_menu(RETURN lj_menu%,lj_s$,lj_t$,t$)
PROCbinfeed_menu("lj",lj_menu%,lj_s$,lj_t$,t$,buff%)
ENDPROC

DEF FNlj_binfeed_save(lj_dir$,lj_s$,lj_t$)
=FNbinfeed_save("lj",lj_dir$,lj_s$,lj_t$,buff%)
