          PH.ARGS DRPT,WORK.ID,OPT,VALUS,MASKS,SS.MASKS,WORK.ITEM,SSEL
** Version# 37 - 01/23/2008 - 05:55pm - AGARZA - main

*** Routine: REP.PHR.WRITER2
*-------------------------------------------------------------------------*
*** Phantom routine that actually prints out the actual report. (From
*** report writer)
*-------------------------------------------------------------------------*
*** DRPT [IN]      - Actual Hold Report created                       (OUT)
*** WORK.ID [IN]   - The Report Writer Work Id                        (IN)
*** OPT [IN]       - Report Options                                   (IN)
*** VALUS [IN]     - Specific Branch Data                             (IN)
*** MASKS [IN]     - Conversions for values output by dict items      (IN)
*** SS.MASKS [IN]  - (IN)
*** WORK.ITEM [IN] - The WORK record                                  (IN)
*** SSEL [IN]      - The Sort Selects                                 (IN)
*-------------------------------------------------------------------------*
*** COMMON USED:
*-------------------------------------------------------------------------*
*** Multi break with null values fix MODS FOR LABELS
*-------------------------------------------------------------------------*
*** ODBC Logic - the ODBC.FILE flag is true whenever and ODBC file will be
*** written. COLUMN.OUT is true whenever the Solar Add On is authorized.
*** If the report is being run without the Add On just to be printed,
*** COLUMN.OUT OR NOT(ODBC.FILE) logic will be followed, generating a
*** printed report. If ODBC.FILE is initially true, data is written to an
*** ODBC.FILE with the passed in name. If COLUMN.OUT is also true, a
*** report will be printed in addition to the file creation. However, if
*** COLUMN.OUT is true but ODBC.FILE is not, an ODBC.FILE will -still- be
*** created using the name ODBC.<PID>. ODBC data is written in internal
*** (unconverted) format, and includes only the lowest level detail or
*** summary lines (no totaling).
*** Check for Solar Reporter Add On
          UT.SEC3 30,AUTH.OK,,NO
          IF AUTH.OK THEN COLUMN.OUT = YES ELSE COLUMN.OUT = NO

          GOSUB INIT

*** Setup the common array DICT.COMMON which dictionaries can then access
          GOSUB GET.DICT

*** Select the IDs from the specified file using the specified select
*** statement to run the report for.
          GOSUB PERFORM.SELECT

*** Printout labels if that's what the user specified.
          DICT.COMMON = SAVE.DICT.COMMON
          IF PRTLBL AND (NOT(ODBC.FILE) OR COLUMN.OUT) THEN
             GOSUB PRT.LBLS
             STOP
          END

*** Setup the heading at the top of the report - If this is an ODBC data
*** source then create the file and dictionaries
          GOSUB SET.HEADER

*** Get a list of records we should evaluate each dictionary item on.
          GOSUB GET.LST

          CUR.LINE = 1
*-------------------------------------------------------------------------*
          LOOP
          READNEXT ID ELSE EXIT
          LINE.CT += 1
          @NI = LINE.CT
          ICNT+=1
          PRE.VAL    = ''
          VAL.STRING = ''
          VAL.STRING.ODBC = ''
          ODBC.REC   = ''
          BRK.ON     = ''
          BRK.INDX   = 0
          LNS        = ''
*-------------------------------------------------------------------------*
*--Pass One - Get nonformula values - *
          READ UDATA FROM MAINFILE,ID THEN
             FOR X = 1 TO VAL.NUM
                DICT.ID = DICTS<1,X>
                DICT.COMMON = RAISE(DICT.COM<X>)
                IF FORMULAS<1,X>='' THEN
                   PINFO = RAISE(RAISE(REM.PATH<1,X>))
                   GET.DICT.VALUE.REMOTE DICT.ID,FLNM,ID,UDATA,PINFO,DICT.VAL,FORM.ERR
                   CONVERT AM TO VM IN DICT.VAL
                   PRE.VAL<X> = DICT.VAL
                END
             NEXT X
*-------------------------------------------------------------------------*
*--Pass Two - Get formula values - *
             FOR VN = 1 TO VAL.NUM
             IF FORMULAS<1,VN>#'' THEN
                GOSUB CALC.RSLT
                PRE.VAL<VN> = RSLT
             END
             NEXT VN
*-------------------------------------------------------------------------*
*--Pass Three - Format String - *
             FOR X = 1 TO VAL.NUM
             DICT.VAL = RAISE(PRE.VAL<X>)
             IF BREAKONS<1,X> AND (NOT(ODBC.FILE) OR COLUMN.OUT) THEN
                BRK.INDX += 1
                BRK.ON<BRK.INDX> = DICT.VAL
             END

*  Wrapping Routine... Need work...
             AM.CT = DCOUNT(DICT.VAL,AM)
             FOR AMN = 1 TO AM.CT
                CONVERT SVM TO VM IN DICT.VAL<AMN>
                TMP = LOWER(DICT.VAL<AMN>)
                VAL.STRING<X,AMN,-1> = TMP
                VAL.STRING.ODBC<X,AMN,-1> = TMP
                TMP.CNT = DCOUNT(TMP,SVM)
                IF TMP.CNT > LNS<2,AMN> THEN LNS<2,AMN> = TMP.CNT ELSE
                   IF ODBC.FILE THEN
                      ST.CT    = TMP.CNT + 1
                      FOR NPOS = ST.CT TO LNS<2,AMN>
                         VAL.STRING.ODBC<X,AMN,NPOS> = VAL.STRING.ODBC<X,AMN,TMP.CNT>
                      NEXT NPOS
                   END
                END
             NEXT AMN

             IF AM.CT > LNS<1> THEN LNS<1> = AM.CT ELSE
                IF ODBC.FILE THEN
                   ST.CT    = AM.CT+1
                   FOR NPOS = ST.CT TO LNS<1>
                      VAL.STRING.ODBC<X,NPOS> = VAL.STRING.ODBC<X,AM.CT>
                   NEXT NPOS
                END
             END

             IF TOTLS<1,X> = '1' OR TOTLS<1,X> = '2' THEN
                CONVERT "," TO "" IN DICT.VAL
                TOTS<1,X>  += SUMMATION(DICT.VAL)
             END
             NEXT X

             IF BRK.CNT AND BRK.ON # PBK AND (NOT(DETAIL) OR NOT(ODBC.FILE) OR COLUMN.OUT) THEN
                IF PBK # '@@' THEN GOSUB BREAKON.RTN
                PBK = BRK.ON
             END
             IF TOT.CNT THEN
                BRK.TOT = ADDS(BRK.TOT,TOTS)
                TOTS    = ''
             END
*** Detail logic for printed and/or ODBC file - data string splits after
*** conversions so that ODBC data is maintained in internal format
             IF DETAIL THEN
                FOR AMV = 1 TO LNS<1>
                   IF (LNS<2,AMV>+0) < 1 THEN LNS<2,AMV> = 1
                   FOR VMV = 1 TO LNS<2,AMV>
                      OP = ''
                      FOR ATTN = 1 TO VAL.NUM
                         FMT = FMTS<1,ATTN>
                         IF VAL.STRING<ATTN,AMV,VMV> # '' THEN
                            IF DICT.FMTS<1,ATTN> THEN
                               TVAL = VAL.STRING<ATTN,AMV,VMV>
                               TVAL.ODBC = VAL.STRING.ODBC<ATTN,AMV,VMV>
                               DICT.CONV = RAISE(DICT.FMTS<1,ATTN>)
                               CONV.CT = DCOUNT(DICT.CONV,VM)
                               IF DCONV<1,ATTN> THEN
                                  TVAL = OCONV(TVAL,DCONV<1,ATTN>)
                                  TVAL.ODBC = OCONV(TVAL.ODBC,DCONV<1,ATTN>)
                                  TVAL = ICONV(TVAL,DICT.CONV<1,CONV.CT>)
                                  TVAL.ODBC = ICONV(TVAL.ODBC,DICT.CONV<1,CONV.CT>)
                               END

                               GOSUB CHK.CONV
                               VAL.STRING<ATTN,AMV,VMV> = TVAL
                               VAL.STRING.ODBC<ATTN,AMV,VMV> = TVAL.ODBC
                            END
                         END

                         IF CDLM THEN
                            CONVERT CDLM TO '' IN VAL.STRING<ATTN,AMV,VMV>
                            CONVERT CDLM TO '' IN VAL.STRING.ODBC<ATTN,AMV,VMV>
                         END

                         TMP = VAL.STRING<ATTN,AMV,VMV> FMT
                         IF ATTN # VAL.NUM AND WIDTHS<1,ATTN> THEN
                            **If col delimiter not space need to trim first
                            IF TRIM.BLKS AND CLMSPC#' ' THEN TMP=TRIM(TMP)
                            TMP = TMP:CLMSPC
                         END

                         IF TRIM.BLKS THEN TMP = TRIM(TMP)
                         IF WIDTHS<1,ATTN> THEN
                            OP = OP:TMP
                         END
                         IF ODBC.FILE THEN
                            THIS.VAL       = VAL.STRING.ODBC<ATTN,AMV,VMV>
                            ODBC.REC<ATTN> = THIS.VAL
                         END
                      NEXT ATTN

                      IF ODBC.FILE THEN
                         IF COLUMN.OUT THEN GOSUB PRT.LINE
                         GOSUB WRT.REC
                      END ELSE
                         GOSUB PRT.LINE
                      END
                   NEXT VMV
                NEXT AMV

                IF SPCS AND (NOT(ODBC.FILE) OR COLUMN.OUT) THEN
                   FOR SPC = 1 TO SPCS
                      PRINT
                   NEXT SPC
                END
             END
          END
          REPEAT

          IF LINE.CT = 0 AND (NOT(ODBC.FILE) OR COLUMN.OUT) THEN
             PRINT "No items selected"
          END ELSE
             LAST.PAGE = YES
             IF (TOT.CNT OR BRK.CNT) AND (NOT(DETAIL) OR NOT(ODBC.FILE) OR COLUMN.OUT) THEN
                IF BRK.CNT THEN GOSUB BREAKON.RTN
                IF NOT(BRK.CNT) THEN
                   GTOL = ADDS(GTOL,BRK.TOT)
                   END
                TTOL = GTOL
                PBK  = ''
                PRINT TOTLN
                GOSUB PRINT.TOT
             END
          END

          IF NOT(ODBC.FILE) OR COLUMN.OUT THEN
             PRINTER.OFF DOC.ID
          END

FINISH:
          IF NOT(ODBC.FILE) OR COLUMN.OUT THEN
             IF COLUMN.OUT THEN
                READU REP.REC FROM RPTFILE,DOC.ID ELSE REP.REC = ''
                GOSUB GET.SBY.INFO
                CONVERT '*' TO '' IN TOTLS
                REP.REC<40> = YES
                REP.REC<41> = FMTS
                REP.REC<42> = TOTLS
                REP.REC<43> = BREAKONS
                REP.REC<44> = DICT.FMTS
                REP.REC<45> = ODBC.HDRS
                REP.REC<46> = LOWER(OLD.DICT.COMMON)
                REP.REC<47> = SORT.BY.INFO
                REP.REC<48> = FORMULAS
                REP.REC<50> = LOWER(WORK.ITEM)
                WRITE REP.REC ON RPTFILE,DOC.ID
             END
          END

          UT.PH.CLEANUP
          EXECUTE 'DELETE-LIST ':SAVELIST.ID:'~':LC:PID$ CAPTURING DMY

          IF ICNT = 0 THEN
             SPOOLER.DELETE DOC.ID
             SEND.MESSAGE 'Phantom',USER.ID,TITLE:' Selected 0 items...No Report Produced'
          END ELSE
             SEND.MESSAGE 'Phantom',USER.ID,TITLE:' is Complete'
          END
          STOP
*-------------------------------------------------------------------------*
GET.SBY.INFO: *** Get the actual columns on the report they sorted by
          SORT.BY.INFO = ''
          SORT.CT      = DCOUNT(SRT.DATA<1>,VM)

          FOR SORTN = 1 TO SORT.CT
             SORT.BY.DICT = SRT.DATA<1,SORTN,1>
             LOCATE SORT.BY.DICT IN DICTS<1> SETTING SORT.LN ELSE NULL
             SORT.BY.INFO<1,SORTN,1> = SORT.LN
             SORT.BY.INFO<1,SORTN,2> = SRT.DATA<1,SORTN,2>
          NEXT SORTN

          RETURN
*-------------------------------------------------------------------------*
WRT.REC:  *** Come here once the new ODBC record is defined and write it to
          *** the newly created ODBC file.
          GET.NEW.ID ODBC.FILE:':NEW.ID',REC.ID,,,ODBCFILE

          IF LEN(REC.ID) < 10 THEN
             REC.ID = REC.ID "R%10"
          END

          WRITE ODBC.REC ON ODBCFILE,REC.ID

          RETURN
*-------------------------------------------------------------------------*
PRT.LINE: *** Print this one line of detailed information
          IF PRT.LINE AND VMV = 1 AND AMV = 1 THEN
             TMP.FMT = "R#":PRT.LINE
             PRINT CUR.LINE TMP.FMT:' ':
             CUR.LINE += 1
          END

          PRINT OP:
          IF RDLM THEN PRINT RDLM: ELSE PRINT

          RETURN
*-------------------------------------------------------------------------*
BREAKON.RTN: *
          BRK.TOL<BRK.CNT> = BRK.TOT
          PAGE.BRK = NO
          FOR P = 1 TO BRK.CNT
          IF LAST.PAGE OR BRK.ON<P> NE PBK<P> THEN
             ODBC.REC = ''
             FOR BLVL = BRK.CNT TO P STEP -1
             BRK.COL  = BRK.POS<1,BLVL>
             TTOL = BRK.TOL<BLVL>
*** ODBC.TOT.FLAG set to yes if this is a base summary line NOT totaled
             IF DETAIL OR BLVL # BRK.CNT THEN
                IF NOT(ODBC.FILE) OR COLUMN.OUT THEN PRINT TOTLN
             END ELSE
                IF ODBC.FILE THEN ODBC.TOT.FLAG = YES
             END
             GOSUB PRINT.TOT
             PLVL = BLVL - 1
             IF PLVL NE 0 THEN
                BRK.TOL<PLVL> = ADDS(BRK.TOL<PLVL>,BRK.TOL<BLVL>)
             END ELSE
                GTOL = ADDS(GTOL,BRK.TOL<1>)
                END
                BRK.TOL<BLVL> = ''
             IF NOT(LAST.PAGE) THEN
                IF BREAKONS<1,BRK.COL> = 'P' THEN PAGE.BRK = YES
             END
             NEXT BLVL

             IF ODBC.REC THEN GOSUB WRT.REC
             IF PAGE.BRK AND (NOT(ODBC.FILE) OR COLUMN.OUT) THEN PRINT CHAR(12)
             BRK.TOT = ''
             RETURN
          END
          NEXT P

          RETURN
*-------------------------------------------------------------------------*
CALC.RSLT:  *
          FRML.STRG = FORMULAS<1,VN>
          FVALS=DCOUNT(FRML.STRG,SVM)
          FOR FVAL = 1 TO FVALS
          IF NUM(FRML.STRG<1,1,FVAL>) THEN
             COL.INDX = FRML.STRG<1,1,FVAL>
             TVAL = PRE.VAL<COL.INDX>
             IF DCONV<1,COL.INDX>#'' THEN TVAL=OCONV(TVAL,DCONV<1,COL.INDX>)
             FRML.STRG<1,1,FVAL> = TVAL
             END
          NEXT FVAL
          CONVERT SVM TO '' IN FRML.STRG
          GET.RESULT FRML.STRG,RSLT
          IF DICT.FMTS<1,VN> # '' THEN
             RSLT = ICONV(RSLT,DICT.FMTS<1,VN>)
          END
          RETURN
*-------------------------------------------------------------------------*
PRINT.TOT: *
          TOT = ''
          TP  = 0
          PRE.VAL = RAISE(TTOL)
          FOR VN = 1 TO VAL.NUM
          OBRKVL = ''
          FMT = FMTS<1,VN>

          IF TOTLS<1,VN> = '1' OR TOTLS<1,VN> = '2' THEN
             TP = TP + 1
             IF FORMULAS<1,VN> = '' OR TOTLS<1,VN> = '1' THEN
                OBRK.TOT = TTOL<1,VN>
                IF DCONV<1,VN> THEN
                   OBRK.TOT = OCONV(OBRK.TOT,DCONV<1,VN>)
                   OBRK.TOT = ICONV(OBRK.TOT,DICT.FMTS<1,VN>)
                END
             END ELSE
                GOSUB CALC.RSLT
                OBRK.TOT = RSLT
             END
             IF DICT.FMTS<1,VN> THEN
                OBRK.TOT = OCONV(OBRK.TOT,DICT.FMTS<1,VN>)
                END
             IF WIDTHS<1,VN> THEN TOT = TOT:OBRK.TOT FMT:CLMSPC

             IF ODBC.TOT.FLAG THEN
                IF DICT.FMTS<1,VN> THEN
                   * Store the ODBC value in internal format, otherwise
                   * when viewing the report from Solar the decimal point
                   * will be in the wrong place.
                   ODBC.REC<VN> = ICONV(OBRK.TOT,DICT.FMTS<1,VN>)
                END ELSE
                   ODBC.REC<VN> = OBRK.TOT
                END
             END

          END ELSE
             IF BRK.COL = VN AND PBK THEN
                IF DETAIL THEN
                   IF WIDTHS<1,VN> THEN TOT = TOT:STR('*',WIDTHS<1,VN>):CLMSPC
                END ELSE
*** Grab ODBC value before conversions
                   OBRK.ODBC = PBK<BLVL>
                   IF DICT.FMTS<1,VN> THEN
                      TVAL = PBK<BLVL>
                      IF DCONV<1,VN> THEN
                         TVAL = OCONV(TVAL,DCONV<1,VN>)
                         TVAL = ICONV(TVAL,DICT.FMTS<1,VN>)
                      END
                      PBK<BLVL> = OCONV(TVAL,DICT.FMTS<1,VN>)
                   END
                   OBRKVL = PBK<BLVL> FMT
                   IF WIDTHS<1,VN> THEN TOT = TOT:OBRKVL FMT:CLMSPC

*** If this field is for this line, add it to the ODBC rec. Also add
*** fields for other lines if they are not null. This way the "one-line"
*** ODBC rec will have the field data from ALL of the printed sum lines
                   IF ODBC.TOT.FLAG THEN ODBC.REC<VN> = OBRK.ODBC
                   IF ODBC.FILE AND ODBC.REC<VN> = '' THEN
                      ODBC.REC<VN> = OBRK.ODBC
                   END
                END
             END ELSE
                IF WIDTHS<1,VN> THEN TOT = TOT:SPACE(WIDTHS<1,VN>+SPC.CT)
                END
             END
          NEXT VN

          IF PRT.LINE THEN TOT = SPACE(PRT.LINE+1):TOT
          IF NOT(ODBC.FILE) OR COLUMN.OUT THEN
             PRINT TOT
             PRINT
          END

          RETURN
*-------------------------------------------------------------------------*
INIT: *** initialize all variables for this routine as well as read the
      *** current WORK record for this report.
         UNIX.PID.GET PID$
          LINE.CT = 0
          DETAIL          = (OPT[1,1] = 'D')
          MASKS           = RAISE(MASKS)
          SS.MASKS        = RAISE(SS.MASKS)
          MASK.CT = DCOUNT(MASKS,AM)
          FOR S = 1 TO MASK.CT
             IF OCONV(MASKS<S>,"MCA") = "VD" THEN
                MASKS<S> = MASKS<S>[2,LEN(MASKS<S>)]
             END
          NEXT S

          CMD.LIST        = ''
          HDG             = ''
          FMTS            = ''
          BRK.POS         = ''
          TOTS            = ''
          BRK.TOT         = ''
          BRK.TOL         = ''
          BRK.COL         = ''
          GTOL            = ''
          DCODE           = ''
          PBK             = '@@'
          ICNT            = 0
          OLD.DICT.COMMON = ''
          LAST.PAGE       = NO
          ODBC.TOT.FLAG   = NO

          DIM WORK(60)
          OPEN 'REP.DESIGNS' TO REPFILE ELSE STOP
          READ NEW.WORK FROM  REPFILE,WORK.ID ELSE NEW.WORK = ''
          WORK.ITEM = RAISE(WORK.ITEM)
          MATPARSE WORK FROM WORK.ITEM

          RW.MSG = "R/W ":WORK.ID
          FLNM       = WORK(2)                ;* File to run this report
          SLCTS      = WORK(3)                ;* select statements to exec
          NEW.SLCTS  = NEW.WORK<3>
          DICTS      = WORK(4)                ;* Dictionary items
          TOTLS      = WORK(5)                ;* flag to total this dict
          WIDTHS     = WORK(6)                ;* column width
          ODBC.HDRS  = WORK(7)                ;* hdrs for cols w/o .....
          HEADERS    = WORK(7)                ;* heading for this column
          BREAKONS   = WORK(8)                ;* break on this column
          TITLES     = WORK(9)                ;* Title for this report
          RSLCT      = WORK(10)               ;* Reselect this report each
          PROMPTS    = WORK(11)               ;* Prompts for dict/selects
          VALS       = WORK(12)
          DVALS      = WORK(13)
          SPCS       = WORK(14)
          DCOMM      = WORK(15)
          CDLM       = WORK(16)
          RDLM       = WORK(17)
          TRIM.BLKS  = WORK(18)
          PRTLBL     = WORK(19)
          LBLSPECS   = WORK(20)
          PRT.PRMT   = WORK(21)
          ADD.PRMT   = WORK(22)
          DCOMM.PRMT = WORK(25)
          DICT.FMTS  = WORK(26)
          SS.PROMPTS = WORK(27)
          SS.VALS    = WORK(28)
          SS.DVALS   = WORK(29)
          SS.DATA    = WORK(30)
          NEW.TM     = NEW.WORK<34>           ;* last time select was done
          SAMP.CT    = WORK(33)               ;* number of samples in sel
          SEL.TM     = WORK(34)               ;* time the select was done
          SRT.DATA   = WORK(46)               ;* sort by information
          PRT.LINE   = WORK(47)
          REM.PATH   = RAISE(WORK(49)<1,1>)   ;* paths to remote dicts
          ODBC.FILE  = WORK(50)<1,1>          ;* ODBC Data source file ID
          ODBC.CLR   = WORK(50)<1,2>          ;* Clear the ODBC file or not
          ODBC.REL   = RAISE(WORK(50)<1,3>)   ;* ODBC Security information
          IF ODBC.FILE AND ODBC.FILE[1,4] # 'ODBC' THEN
             ODBC.FILE = 'ODBC.':ODBC.FILE
          END

          *** If the user didn't want us to re-select this report from the
          *** file then use the active lists (GET-LIST) instead.
          IF NOT(RSLCT) THEN
             IF SEL.TM # NEW.TM THEN
                RSLCT = YES
             END ELSE
                LC = 0
                FOR LL = 1 TO 5 UNTIL LC
                   IF SLCTS<1,(6-LL)> # '' THEN LC = 6 - LL
                NEXT LL
                IF LC < 1 THEN LC = 1; RSLCT = YES
                WORK(3)<1,11> = LC
             END
          END
          READ CTRL.REC FROM CTRLFILE,'PROMPT.CONTROL' ELSE CTRL.REC=''
          TOT.WIDTH  = WORK(31)
          IF CDLM THEN
             CLMSPC = CDLM
             SPC.CT = LEN(CDLM)
          END ELSE
             CLMSPC = ' '
             SPC.CT = 1
          END
          HDGSPC = ' '
          IF PRT.PRMT = '' THEN PRT.PRMT = 1
*-------------------------------------------------------------------------*
*--- Open the correct files *

          OPEN FLNM TO MAINFILE ELSE
             SEND.MESSAGE 'Phantom' , USER.ID,' Unable to open ',FLNM,' File - Program Aborted'
             STOP
          END

          * Update the last date/time that the report was run
          RW.SET.LAST.RUN.TIME WORK.ID,MAT WORK
          RETURN
*-------------------------------------------------------------------------*
PERFORM.SELECT: * Select the items from the file based on the user specific
          ***  select information (Select screen of rep writer)
          SAVELIST.ID = WORK.ID
          PATH.INFO = WORK(49)
          SAVE.DICT.COMMON = DICT.COMMON

          PROMPT.CT = DCOUNT(SS.VALS,VM)
          SS.VALUS = ''
          FOR S = 1 TO PROMPT.CT
             IF SS.DATA<1,S> # '' THEN
                IF SS.VALS<1,S> = "$BRTERR$" THEN
                   BR.DATA = SS.DATA<1,S>
                   IF BR.DATA = 'All' THEN BR.DATA = 'ALL'

                   IF DCOUNT(BR.DATA,SSVM) > 1 THEN
                      *Already validated in SOLAR, just change to comma
                      *delimited
                      BRCHS          = RAISE(RAISE(BR.DATA))        ;*VM
                      SS.VALUS<1,S>  = RAISE(BR.DATA)               ;*SVM
                      BR.DATA        = CONVERT(SSVM,',',BR.DATA)    ;*,delimitted
                   END ELSE
                      VERIFY.BR BR.DATA,NAME,BRCHS,YES,YES
                      SS.VALUS<1,S>  = LOWER(BRCHS)
                   END

                   DICT.COMMON<1> = BRCHS
                   DICT.COMMON<2> = BR.DATA
                END ELSE
                   CONV.VAL = SS.DATA<1,S>
                   IF OCONV(SS.MASKS<S>,"MCA") = "D" AND NOT(NUM(CONV.VAL)) THEN
                      DATE.VAL = ICONV(CONV.VAL,"D")
                      IF DATE.VAL = '' THEN
                         DATE.VAL = REALDATE(CONV.VAL,DATE())
                      END
                      CONV.VAL = DATE.VAL
                   END
                   IF SS.DVALS<1,S,2> # '' THEN
                      DICT.COMMON<(SS.DVALS<1,S,2>)> = CONV.VAL
                   END
                   VAL.CT = DCOUNT(CONV.VAL,SVM)
                   FOR V = 1 TO VAL.CT
                      IF SS.MASKS<S> THEN CONV.VAL<1,1,V> = OCONV(CONV.VAL<1,1,V>,SS.MASKS<S>)
                   NEXT V
                   IF VAL.CT > 1 THEN
                      CONVERT SVM TO ";" IN CONV.VAL
                   END
                   SS.VALUS<1,S>  = CONV.VAL
                END
             END
          NEXT S

          IF INDEX(TITLES,"$",1) OR INDEX(TITLES,"!",1) THEN
             REP.SEL.REPL TITLES,SS.VALS,SS.VALUS
          END

          IF DRPT<33> = '' THEN
             TITLE    = (TITLES<1,1>:" ":TITLES<1,2>)'L#46'
             IF RDLM THEN TITLE = "** ":TITLE
          END ELSE
             TITLE = DRPT<33>
          END

          IF NOT(RSLCT) THEN RETURN

          LC        = 1
          SLCT.PLUS = ''
          MSG = 'Selecting ':TITLE
          GOSUB WRT.STAT
          REP.SLCT.PLUS FLNM,SLCT.PLUS,WORK.ID

          SET.DATA = YES
          FOR X = 1 TO 5
          SEL.CMD = SLCTS<1,X>
          IF SEL.CMD THEN
             IF SET.DATA THEN
                SET.DATA = NO
                IF SLCT.PLUS THEN
                   RW.EXECUTE.CMD FLNM,SLCT.PLUS,SAVELIST.ID,10,X,PATH.INFO,ERR.MSG
                END
             END
             REP.SEL.REPL SEL.CMD,SS.VALS,SS.VALUS,YES
             CMD.LIST<LC> = SEL.CMD
             RW.EXECUTE.CMD FLNM,SEL.CMD,SAVELIST.ID,LC,X,PATH.INFO,ERR.MSG
             IF ERR.MSG THEN
                SEND.MESSAGE 'Phantom' ,USER.ID,ERR.MSG
                STOP
             END ELSE
                WORK(3)<1,11> = LC
                LC = LC + 1
                EXECUTE 'DELETE-LIST ':SAVELIST.ID:'~':LC:PID$ CAPTURING DMY
             END
          END
          NEXT X

* RESET DICT.COMMON AFTER SELECTIONS
          RETURN
*-------------------------------------------------------------------------*
GET.DICT: *
          Q = DCOUNT(DVALS,VM)
          FOR S = 1 TO Q
          DICT.POS = DVALS<1,S,2>
          IF DICT.POS THEN
             BEGIN CASE
             CASE DICT.POS = 2
                BR.DATA = VALUS<1,S>
                IF BR.DATA = 'All' THEN BR.DATA = 'ALL'

                IF DCOUNT(BR.DATA,SSVM) > 1 THEN
                   *Already validated in SOLAR, just change to comma
                   *delimited
                   BRCHS       = RAISE(RAISE(BR.DATA))        ;*VM
                   VALUS<1,S>  = RAISE(BR.DATA)               ;*SVM
                   BR.DATA     = CONVERT(SSVM,',',BR.DATA)    ;*,delimitted
                END ELSE
                   VERIFY.BR BR.DATA,NAME,BRCHS,YES,YES
                   VALUS<1,S>  = LOWER(BRCHS)
                END

                DICT.COMMON<1> = BRCHS
                DICT.COMMON<2> = BR.DATA
             CASE DICT.POS = 3 OR DICT.POS = 4
                CONV.VAL = VALUS<1,S>
                IF NUM(CONV.VAL) THEN
                   DATE.VAL = CONV.VAL
                END ELSE
                   DATE.VAL = ICONV(CONV.VAL,"D")
                   IF DATE.VAL = '' THEN
                      DATE.VAL = REALDATE(CONV.VAL,DATE())
                   END
                   CONV.VAL = DATE.VAL
                END
                DICT.COMMON<DICT.POS> = DATE.VAL
                VALUS<1,S> = OCONV(DATE.VAL,MASKS<S>)
             CASE 1
                DICT.COMMON<DICT.POS> = VALUS<1,S>
             END CASE
          END ELSE
             CONV.VAL = VALUS<1,S>
             IF OCONV(MASKS<S>,"MCA") = "D" AND NOT(NUM(CONV.VAL)) THEN
                DATE.VAL = ICONV(CONV.VAL,"D")
                IF DATE.VAL = '' THEN
                   DATE.VAL = REALDATE(CONV.VAL,DATE())
                END
                CONV.VAL = DATE.VAL
             END
             VAL.CT = DCOUNT(CONV.VAL,SVM)
             FOR V = 1 TO VAL.CT
                IF MASKS<S> THEN CONV.VAL<1,1,V> = OCONV(CONV.VAL<1,1,V>,MASKS<S>)
             NEXT V
             IF VAL.CT > 1 THEN
                CONVERT SVM TO ";" IN CONV.VAL
             END
             VALUS<1,S>  = CONV.VAL
          END
          NEXT S
          OLD.DICT.COMMON = DICT.COMMON

*--- Set formats for Dict items and determine Heading length *
***********************************************************
          TOT.CNT  = 0
          TOTLN    = ''
          COLEN    = TOT.WIDTH
          DCONV    = ''
          DICT.COM = ''
          FORMULAS = ''
*         FTOT.VAL = ''
          DCMCNT = DCOUNT(CTRL.REC,AM)
          VAL.NUM = DCOUNT(DICTS<1>,VM)
          FOR Y   = 1 TO VAL.NUM
          DICTID = FIELD(DICTS<1,Y>,',',1)
          TRUE.FILE = ''
          TRUE.DICT = ''
          RW.PARSE.DICT.ID DICTID,FLNM,TRUE.FILE,TRUE.DICT
          READ DICTREC FROM EDICTFILE,TRUE.FILE:"~":TRUE.DICT THEN
*---Dictionary Item
             DCODE<1,Y>    = DICTREC<1>
             MSK  = DICTREC<7>
             JST  = DICTREC<9>
             IF JST = '' THEN JST = 'L'
             IF MSK[1,2]="MR" THEN
                DCONV<1,Y> = MSK
                JST  = 'R'
             END
          END ELSE
*---Formula
             JST  = 'R'
             FORMULA = DICTS<1,Y>
             REP.VERF.FORMULA FORMULA,FORM.ERR,4,Y
             FORMULAS<1,Y>=FORMULA
             MSK  = DICT.FMTS<1,Y>
             END
          IF DICT.FMTS<1,Y> = '' AND MSK # '' THEN
             DICT.FMTS<1,Y>  = MSK
          END
          FMTS<1,-1> = JST:'#':WIDTHS<1,Y>
          IF TOTLS<1,Y> = '1' OR TOTLS<1,Y> = '2' THEN
             IF WIDTHS<1,Y> THEN TOTLN = TOTLN:STR('=',WIDTHS<1,Y>):CLMSPC
             TOT.CNT += 1
          END ELSE
             IF WIDTHS<1,Y> THEN TOTLN = TOTLN:SPACE(WIDTHS<1,Y>+SPC.CT)
          END

          IF BREAKONS<1,Y> THEN
             BRK.POS<1,-1> = Y
          END
          FOR DCMV = 1 TO DCMCNT
          IF DCOMM<1,Y,DCMV> # '' THEN
             DICT.COM<Y,DCMV>=RAISE(DCOMM<1,Y,DCMV>)
             IF DCMV = 3 OR DCMV = 4 THEN
                CONV.VAL = DICT.COM<Y,DCMV>
                IF NOT(NUM(CONV.VAL)) THEN
                   DATE.VAL = ICONV(CONV.VAL,"D")
                   IF DATE.VAL = '' THEN
                      DATE.VAL = REALDATE(CONV.VAL,DATE())
                   END
                   CONV.VAL = DATE.VAL
                END
                DICT.COM<Y,DCMV> = CONV.VAL
                END
          END ELSE
             DICT.COM<Y,DCMV>= LOWER(DICT.COMMON<DCMV>)
          END
          NEXT DCMV
          NEXT Y

          IF PRT.LINE THEN TOTLN = SPACE(PRT.LINE+1):TOTLN
          FULLEN  = LEN(TOTLN)
          BRK.CNT = DCOUNT(BRK.POS,VM)

          RETURN
*-------------------------------------------------------------------------*
SET.HEADER: *
          IF COLEN < 80 THEN COLEN = 80

*-----Title
          SPC1     = (COLEN - LEN(TITLES<1,1>)) / 2
          HDG<1,1> = SPACE(SPC1):TITLES<1,1>:SPACE(SPC1-12):'PAGE:^#####'
          IF TITLES<1,2> THEN
             SPC2     = (COLEN - LEN(TITLES<1,2>)) / 2
             HDG<1,2> = SPACE(SPC2):TITLES<1,2>
             HDL      = 3
          END ELSE
             HDL      = 2
          END


          * see if any links to remote dictionaries are broken
          PATH.ERRS     = ''
          RW.VALIDATE.FILE.PATH MAT WORK,,PATH.ERRS
          IF PATH.ERRS THEN
             * Append broken links to report header
             HDG = INSERT(HDG,1,HDL;VM:LOWER(PATH.ERRS))
             HDL = DCOUNT(HDG<1>,VM)+1
          END

          HDLN     = 0
*-----Prompts
          IF PRT.PRMT THEN
             HDL = HDL+1
             HDG<1,HDL> = STR('*',COLEN)
             HDL = HDL+1
             HDG<1,HDL> = '* Report ID : ':WORK.ID:' '
             R = DCOUNT(PROMPTS,VM)
             FOR N = 1 TO R
             HVAL  = VALUS<1,N>
             IF HVAL # '' THEN
                IF COUNT(HVAL,SVM) THEN
                   CONVERT SVM TO ',' IN HVAL
                   COMMA.COMPRESS HVAL,HVAL
                   END
                IF OCONV(MASKS<N>,"MCA")[1,2] = "YN" THEN
                   NXTP = PROMPTS<1,N>:" ":'NY'[(HVAL+1),1]
                END ELSE
                   NXTP = PROMPTS<1,N>:" ":OCONV(HVAL,MASKS<N>)
                END
                IF HDLN + LEN(NXTP) GT COLEN THEN
                   HDL        = HDL+1
                   HDG<1,HDL> = '* '
                   HDLN       = 0
                   END
                IF HDLN  <= 2 THEN SSCS = '' ELSE SSCS = " ; "
                HDG<1,HDL> = HDG<1,HDL>:SSCS:NXTP
                HDLN       = LEN(HDG<1,HDL>)
             END
             NEXT N
             R = DCOUNT(SS.PROMPTS,VM)
             IF RSLCT THEN
                SEL.MSG = TIMEDATE()
             END ELSE
                SEL.MSG = SEL.TM
             END
             IF SAMP.CT THEN
                SAMP.MSG = "  Sample ":SAMP.CT
             END ELSE
                SAMP.MSG = ''
             END
             HDL        = HDL+1
             HDG<1,HDL> =  "* Selected  : ": SEL.MSG : SAMP.MSG
             HDLN       = 2
             HDL        = HDL+1
             HDG<1,HDL> = '* '
             FOR N = 1 TO R
             HVAL  = SS.DATA<1,N>
             IF HVAL # '' THEN
                HVAL  = SS.VALUS<1,N>
                IF COUNT(HVAL,SVM) THEN
                   CONVERT SVM TO ',' IN HVAL
                   COMMA.COMPRESS HVAL,HVAL
                   END
                CONVERT ';' TO ',' IN HVAL
                IF OCONV(SS.MASKS<N>,"MCA")[1,2] = "YN" THEN
                   NXTP  = SS.PROMPTS<1,N>:" ":'NY'[(HVAL+1),1]
                END ELSE
                   NXTP  = SS.PROMPTS<1,N>:" ":HVAL
                END
                IF HDLN + LEN(NXTP) GT COLEN THEN
                   HDL        = HDL+1
                   HDG<1,HDL> = '* '
                   HDLN       = 0
                   END
                IF HDLN <= 2 THEN SSCS = '' ELSE SSCS = " ; "
                HDG<1,HDL> = HDG<1,HDL>:SSCS:NXTP
                HDLN       = LEN(HDG<1,HDL>)
             END
             NEXT N
             HDL = HDL+1
             HDG<1,HDL> = STR('*',COLEN)
             HDL = HDL+2
          END

*** Column headings
          TRY2 = NO
          GOSUB SET.COL.HDGS

          MSG = 'Spooling ':TITLE
          GOSUB WRT.STAT
          LC = WORK(3)<1,11>

          RETURN
*-------------------------------------------------------------------------*
SET.COL.HDGS: *** Setup the heading for each column on the report.

          IF INDEX(HEADERS,"$",1) AND SS.VALUS # '' THEN
             REP.SEL.REPL HEADERS,SS.VALS,SS.VALUS
          END

          *** Report logic for column headings
          NLNS  = 1
          FOR X = 1 TO VAL.NUM
          IF LEN(HEADERS<1,X>) GT WIDTHS<1,X> AND WIDTHS<1,X> AND HEADERS<1,X,2> = '' THEN
             FOLD HEADERS<1,X>,WIDTHS<1,X>,HDRS,NL
             HDRS = LOWER(HDRS)
             HEADERS<1,X> = HDRS
             END
          IF HEADERS<1,X,2> # '' THEN
             NL = DCOUNT(HEADERS<1,X>,SVM)
             IF NL GT NLNS THEN NLNS = NL
          END
          NEXT X
          FOR X = 1 TO VAL.NUM
          HDDL = HDL
          FOR NLS = 1 TO NLNS
          IF WIDTHS<1,X> THEN
             *** Only add to the header if the column has width.
             IF HEADERS<1,X,NLS> NE '' THEN
                HEADERS<1,X,NLS> = HEADERS<1,X,NLS>:STR(".",WIDTHS<1,X>)
                HEADERS<1,X,NLS> = HEADERS<1,X,NLS>[1,WIDTHS<1,X>]
             END ELSE
                HEADERS<1,X,NLS> = STR(" ",WIDTHS<1,X>)
             END
             HDG<1,HDDL>  = HDG<1,HDDL>:HEADERS<1,X,NLS>:HDGSPC
          END

          IF PRT.LINE AND X = 1 THEN
             IF NLS = 1 THEN
                TMP.FMT = "L#":PRT.LINE
                TMP.WID = PRT.LINE - 5
                IF TMP.WID < 0 THEN TMP.WID = 0
                TMP.PRT = "Line#":STR('.',TMP.WID)
                HDG<1,HDDL> = TMP.PRT TMP.FMT:' ':HDG<1,HDDL>
             END ELSE
                HDG<1,HDDL> = SPACE(PRT.LINE+1):HDG<1,HDDL>
             END
          END

          HDDL+=1
          NEXT NLS
          NEXT X

          IF NOT(ODBC.FILE) OR COLUMN.OUT THEN
             PRINTER.ON COLEN,TITLE,DOC.ID,HDG,RPT.DFLT=DRPT
          END
          IF NOT(ODBC.FILE) AND COLUMN.OUT THEN ODBC.FILE = 'ODBC.':DOC.ID

          IF ODBC.FILE THEN
             *** this routine will go out and create the needed dict items
             *** on the ODBC file for retrieving the data at a later time
RETRY:       UT.OPEN.FILE ODBC.FILE,ODBCFILE,ERR.MSG,YES

             BEGIN CASE
             CASE ERR.MSG AND NOT(TRY2)
                EXECUTE "CREATE-FILE ":ODBC.FILE:" 1 500,4,30" CAPTURING MG
                TRY2 = YES
                GOTO RETRY
             CASE ERR.MSG
                SEND.MESSAGE 'Phantom',USER.ID,TITLE:' ':ERR.MSG
                STOP
             END CASE

             IF COLUMN.OUT THEN
                WORK.ITEM<50> = ODBC.FILE:VM:YES:VM:YES
             END

             ODBC.SET.DICTS ODBC.FILE,WORK.ITEM
             RETURN
          END
          RETURN
*-------------------------------------------------------------------------*
GET.LST: * Get list of appropriate items based on the select criteria
          IF RSLCT THEN
             GET.LID = SAVELIST.ID:'~':LC:PID$ ;* get.list ID
          END ELSE
             GET.LID = SAVELIST.ID:'~':LC
          END
          GL.EXEC = "GET-LIST ":GET.LID
          EXECUTE GL.EXEC CAPTURING MSG

          IF SYSTEM(11) = 0 THEN
             RETURN TO FINISH
          END

          IF SAMP.CT > 0 THEN
             COMMAND = "SELECT ":FLNM:" (":SAMP.CT
             EXECUTE COMMAND PASSLIST CAPTURING MSG
          END

          RETURN
*-------------------------------------------------------------------------*
PRT.LBLS: LISTNAME = SAVELIST.ID:'~':WORK(3)<1,11>
          IF RSLCT THEN
             LISTNAME := PID$
          END

          GL.EXEC  = "GET-LIST ":LISTNAME
          EXECUTE GL.EXEC CAPTURING MSG
          IF SYSTEM(11) = 0 THEN
             SEND.MESSAGE 'Phantom',USER.ID,TITLE:' has selected 0 items - No labels produced'
             STOP
          END

          IF SAMP.CT > 0 THEN
             COMMAND = "SELECT ":FLNM:" (":SAMP.CT
             EXECUTE COMMAND PASSLIST CAPTURING MSG
          END

          CNT     = LBLSPECS<1,1>
          SIZ     = LBLSPECS<1,5>
          SPAC    = LBLSPECS<1,6>
          COLEN   = (CNT * (SIZ + SPAC))
          IF CNT > 1 THEN COLEN = COLEN - SPAC
          IF COLEN < 80 THEN COLEN = 80
* Sent the Auto formfeed to disabled
          DRPT<32> = YES

          PRINTER.ON COLEN,TITLE,DOC.ID,RPT.DFLT=DRPT

          *** send the formats to REP.PHR.LABELS
          DICTS = DICTS:AM:DICT.FMTS:AM:REM.PATH

          REP.PHR.LABELS FLNM,LBLSPECS,DICT.COM,DICTS,VAL.NUM,WIDTHS,MAINFILE,DICTFILE,HEADERS

          PRINTER.OFF DOC.ID
          SEND.MESSAGE 'Phantom',USER.ID,TITLE:' is Complete'

          RETURN
*-------------------------------------------------------------------------*
CHK.CONV: *** Put any dates or numeric fields for ODBC files into internal
          *** format so SELECT and SSELECT will work correctly.
          FOR CC = 1 TO CONV.CT
             *** OCONV both sets of values
             TVAL = OCONV(TVAL,DICT.CONV<1,CC>)
             TVAL.ODBC = OCONV(TVAL.ODBC,DICT.CONV<1,CC>)

             IF ODBC.FILE THEN
                *** ICONV the ODBC values but NOT the others
                IF DICT.CONV<1,CC>[1,2]='MR' OR DICT.CONV<1,CC>[1,1]='D' THEN
                   TVAL.ODBC = ICONV(TVAL.ODBC,DICT.CONV<1,CC>)
                END
             END
          NEXT CC

          RETURN
*-------------------------------------------------------------------------*
WRT.STAT: *** Write out the status of the report on the phantom status file
          MSG<2> = RW.MSG
          MSG<3> = USER.ID

          WRITE MSG ON PHSTFILE,PID$
          RETURN
!AGARZA~01/23/08~17:55
