tips:revmedia:v1i5a4

Merge Processor

Published ByDateVersionKnowledge LevelKeywords
Sprezzatura Ltd01 OCT 19891.15+EXPERTMERGE, PROCESSOR, MAKEMERGE, FONT, PRINTER

As the sophistication of our user base grows, so does the sophistication of their demands. A recent case in point was a client who had a twin-bin feeder on their laser printer and who wanted a MERGE document to print first page on headed paper and then second page (and all subsequent pages) on continuation paper.

This obviously involved swapping printer bins with the appropriate escape sequence using a «FONT1» and a «FONT2» command. (Just in case you hadn't noticed, pressing F10 when in the MAKEMERGE window gives you the MERGE menu and allows you to configure your printer etc.). The only problem with this approach was that issuing a swap bin command to the laser printer caused a form feed. This in itself was not a problem, but AREV was not aware that a page throw had occurred and thus continued printing until it reached the end of its logical page and then performed a form feed itself. Thus if we were printing an 80 line document with a page length of 60 lines, and we swapped bins after 40 lines, AREV printed a further 20 lines on the next page and then form fed to print the final 20 lines on the third page.

This was really inconvenient. What was required was a «PAGE.NO.FF» command to reset the line counter to 0 without printing a CHAR(12). Without access to source, I can only suggest this as a possible enhancement - so short term, I developed a solution to work around this problem.

In the object code for MERGE is contained a literal about "to process". By experimenting I discovered that if you put a subroutine name preceded with an @ sign into the PRINTER field on the MERGE document (NB @Routine.name NOT @S Routine.name@), the partially formatted document is sent to your routine NOT to the printer. The subroutine is passed two parameters, the id of the record and the formatted text. All of the printer control commands are left in«ITAL», «END.ITAL», «FF» etc. but all paragraph formatting has been done. We only need to process this data and ignore the form feeds, applying our own page control logic. In fact this has much wider application. We could do ANYTHING with the output, write it direct to a WP file, create a fax file for pickup by JT-Fax - anything.

In addition to the information passed directly to the subroutine we also need access to an area of system labelled common called MERGE. This labelled common area has 26 parameters (I.E. COMMON / MERGE / A,B,C,D,E,F,G,H,I,J,K, L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z) which are as follows (where ??? is a variable of unknown usage)

    A    Data File Name
    B    Dictionary File Variable
    C    ???
    D    Special Text Data File Name
    E    Top Margin
    F    Left Margin
    G    Page Width - (Left Margin + Right Margin)
    H    Page Height - (Top Margin + Bottom Margin)
    I    Default Format (Coded - 0 = Noformat, ! = Left, 2 = filled)
    J    Heading
    K    Footing
    L    Formatted text - identical to second parameter passed
    M-P  ???
    Q    %FIELDS% of Data File
    R    File Variable of Special Text Data File
    S,T  ???
    U    Field mark delimited list of command options , <<, >>, <<FORMAT>>
         etc.
    V    Field mark delimited list of printer control codes, <<BOLD>>,
         <<END.BOLD>> etc.
    W    Special Merge Fields, MRG.DATE, MRG.TIME etc.
    X    <<VB>>
    Y    <<VBH>>
    Z    <<FF>>

Thus our bin change logic could look something like (assuming HP.DESKJET printer and bin changes in «FONT1» and «FONT2» and with apologies for tersity of code)

  SUBROUTINE PRINT.MERGE(ID,TEXT)
       COMMON /MERGE/ A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z
       EQU PRN$          TO "HP.DESKJET"
       EQU PAGE.LEN$     TO 60
       PRIN.CODES = XLATE("MRG.PRINTER.CONFIG"'PRN$,"","X")
       * Get control codes for bin changes
       CODE = "<<FONT1>>" ; GOSUB GET.CODES ; BIN1 = CODES
       CODE = "<<FONT2>>" ; GOSUB GET.CODES ; BIN2 = CODES
       CTR = COUNT(TEXT,@FM) + (TEXT#"")
       FIRST.PASS = 1 ; PRINTER ON ; PRINT BIN1 ; LINE.CTR= 0
       FOR LINE = 1 TO CTR
            CL =TEXT<LINE> ; NO.MORE.CHANGES = 0
            LOOP UNTIL NO.MORE.CHANGES DO
                 QX = INDEX(CL,"<<",1)
                 IF QX THEN
                      CODE = CL[QX,"F>>"] : ">>" ; S.COL2 = COL2()
                       IF CODE = "<<FF>>" THEN CODE = "" ELSE
                           GOSUB GET.CODES
                       END
                       CL = CL[1,QX-1] : CODE : CL[S.COL2+1,9999]
                 END ELSE NO.MORE.CHANGES = 1
            REPEAT
            PRINT CL ; LINE.CTR += 1
            IF LINE.CTR = PAGE.LEN$ THEN
                 IF FIRST.PASS THEN
                      PRINT BIN2 ; FIRST.PASS = 0
                 END ELSE PRINT CHAR(12)
                 LINE.CTR = 0 ; *Reset line count
            END
       NEXT
       PRINT CHAR(12) ; PRINTER OFF
  RETURN

  GET.CODES:
       LOCATE CODE IN V USING @FM SETTING POS THEN
            CODES = ""
            NEW.CTR = COUNT(PRIN.CODES<POS>," ") + 1
            FOR BX = 1 TO NEW.CTR
                    CODES :=CHAR(FIELD(PRIN.CODES<POS>," ",BX))
            NEXT
       END
  RETURN

(Volume 1, Issue 5, Pages 4,9)

  • tips/revmedia/v1i5a4.txt
  • Last modified: 2024/06/19 20:20
  • by 127.0.0.1