home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / LASER / LASR4UP2.ZIP / LASER4UP.ASM next >
Encoding:
Assembly Source File  |  1990-02-12  |  40.7 KB  |  1,071 lines

  1.         PAGE    75,132
  2.         TITLE   "LASERLST - List file to HP LaserJet"
  3. ;
  4. ; The original LASERLST program by Michael Holmes and Bob Flanders formats
  5. ; and prints two 80-column pages side-by-side on one 8.5x11 inch page on
  6. ; a HP LaserJet printer.  The program thus allows you to cut your paper
  7. ; usage in half.
  8. ;
  9. ; The LASER4UP program is the LASERLST program modified to send what would
  10. ; be every other *physical* page to a disk file with all the appropriate 
  11. ; LaserJet control codes. This allows you to print on the front side of
  12. ; each page, then put the pages back into the original order, flip them
  13. ; over in the printer, and then print every other physical page on the
  14. ; back.  This cuts your paper usage to one-fourth of what it would have 
  15. ; been without LASERLST or LASER4UP.  LASERLST would work fine without
  16. ; modification if everyone was using the LaserJet IID, which has the
  17. ; capability of printing on the back side of the page automatically.
  18. ; Unfortunately, this is not so... LASER4UP requires re-sorting the 
  19. ; printed output and re-inserting that back into the printer, so it's a bit
  20. ; more trouble to use than LASERLST, but it does have the advantage of 
  21. ; minimizing the paper required to print your documentation or program 
  22. ; listings.
  23. ;
  24. ; Original LASERLST program by Michael Holmes and Bob Flanders
  25. ; Modified LASER4UP program by Bob White 3/28/89.
  26. ; Minor bug fixed by Bob White 8/17/89 (program lost track of pages
  27. ;  when a file had only one page in it and the program was printing
  28. ;  multiple files.)
  29. ;
  30. ; Minor bug fixed by Bob White on 2/12/90 to let the program work on
  31. ;  a LaserJet IIP printer.  Reversed two escape sequences.  See PC Mag,
  32. ;  2/27/90, Vol 9 #4, P. 338 for more info.
  33. ;
  34. CSEG        SEGMENT PARA PUBLIC 'CODE'
  35.         ASSUME  CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
  36.         ORG     100H
  37.  
  38. START:        JMP     MAIN            ; go to start of program
  39.  
  40. HEADER_MSG  DB        "LaserLst 1.0 (c) 1989 Ziff Communications Co.", 0DH,0AH
  41.         DB        "PC Magazine",254," Michael Holmes & Bob Flanders",0DH,0AH
  42.             DB      "Laser4up 1.1",254," Bob White 2/12/90",0Dh,0Ah
  43. CRLF        DB        0DH,0AH
  44. DOLLAR        DB        "$"
  45. ; ---------------------------------------------------------------------------
  46. ;   Initialized work areas
  47. ; ---------------------------------------------------------------------------
  48. ARG1        DW        0                ; addr of first argument
  49. ARG2        DW        0                ; addr of second argument
  50. CHandle     DW      0                       ;; Current output handle
  51. NHandle     DW      0                       ;; Next output handle
  52. BHandle     DW      0                       ;; Back side file handle
  53. PHANDLE     DW        4                ; printer handle (stdprn)
  54. TABCOL        DW        8                ; tab width
  55. NEWPAGE     DB        0                ; new page requested flag
  56. HPSTATE     DB        0                ; printer state  (1 = initialized)
  57. BackFile    DB      "LASER4UP.TXT",0        ;; ASCIIZ back side file name
  58.  
  59. TITLE_        DB        1BH,"&dD"               ; title line for heading
  60. TITLE_DTE   DB        "mm/dd/yyyy  "          ; ..and display
  61. TITLE_TME   DB        "hh:mm       Filename: "
  62. TITLE_FLE   DB        19 dup(32)
  63. TITLE_DSP   EQU     $-TITLE_DTE
  64.         DB        "                    Page"
  65. TITLE_PGE   DB        "xxxx",0dh,0ah,0ah
  66.         DB        1BH,"&d@"
  67. TITLE_LEN   EQU     $-TITLE_            ; length of title
  68. ;----------------------------------------------------------------------
  69. ;   DTA structure for DOS "find matching" call
  70. ;----------------------------------------------------------------------
  71. DTA        EQU     80H             ; dta offset
  72. DTA_ATTR    EQU     BYTE PTR DTA+21        ; file attribute
  73. DTA_TIME    EQU     WORD PTR DTA_ATTR+1     ; file time
  74. DTA_DATE    EQU     WORD PTR DTA_TIME+2     ; file date
  75. DTA_LSIZ    EQU     WORD PTR DTA_DATE+2     ; file lsw of size
  76. DTA_HSIZ    EQU     WORD PTR DTA_LSIZ+2     ; file msw of size
  77. DTA_NAME    EQU     BYTE PTR DTA_HSIZ+2     ; file name of file
  78. DTA_LEN     EQU     DTA_NAME+15-DTA        ; length of dta find entry
  79. ;----------------------------------------------------------------------
  80. ;   Messages to user
  81. ;----------------------------------------------------------------------
  82. FILENF        DB        "File not found.",0DH,0AH,"$"
  83. PRTOERR     DB        "Could not open output file.",0DH,0AH,"$"
  84. Backerr     DB      "Could not open back side output file.",0Dh,0Ah,"$"
  85. FORMAT        DB        0DH,0AH,"SYNTAX:",09H,"LASERLST [d:][path]filename[.ext] "
  86.         DB        "[outfile] [/Tn]",0DH, 0AH, 0AH
  87.         DB        "  ofile defaults to LPT1:",0DH,0AH
  88.         DB        "  n is tab width (16 max)",0DH,0AH,"$"
  89. ;----------------------------------------------------------------------
  90. ;   HP control strings
  91. ;----------------------------------------------------------------------
  92. STRING1     DB        1BH,"E",1BH,"&l1O",1BH,"(s17H",1BH,"&l5.14C"
  93.         DB        1BH,"&l6E",1BH,"&l71F",1BH,"(s-3B"
  94.         DB        1BH,"&a0R",1BH,"&a85M",1BH,"&a5L",0DH
  95. STRING1_LEN EQU     $-STRING1
  96.  
  97. STRING2     DB        0ch,1BH,"E"
  98. STRING2_LEN EQU     $-STRING2
  99.  
  100. STRING3     DB        1BH,"&a0R",1BH,"&a90M",1BH,"&a88L",0DH,0AH,0DH,0AH
  101. STRING3_LEN EQU     $-STRING3
  102.  
  103. STRING4     DB        "|", 0DH,0AH
  104.  
  105. STRING5     DB        1BH,"&a0R",1BH,"&a171M",1BH,"&a91L",0DH
  106. STRING5_LEN EQU     $-STRING5
  107.  
  108. ;
  109. ; Note: leading formfeed (0Ch) replaced by carriage return (0Dh) for
  110. ; the first pass through each input file.  Changed to FF in code.
  111. ;
  112. STRING6     DB        0Dh,1BH,"&a0R",1BH,"&a85M",1BH,"&a5L",0DH
  113. STRING6_LEN EQU     $-STRING6
  114. ; ---------------------------------------------------------------------------
  115. ;   MAIN - Mainline of program
  116. ; ---------------------------------------------------------------------------
  117. MAIN        PROC                ; start of program
  118.  
  119.         CALL    INIT            ; initialize program
  120.  
  121. MAIN10:     CALL    OPEN            ; open the input file
  122.         JC        MAIN80            ; if we can't .. try next
  123.  
  124. MAIN20:     CALL    READ            ; read a block
  125.  
  126.         CALL    PRINT            ; print the line
  127.  
  128.         OR        SI, SI            ; q. end of file?
  129.         JNZ     MAIN20            ; a. no .. get next line
  130.  
  131.         MOV     BX, FHANDLE         ; bx = input file handle
  132.         MOV     AH, 3EH            ; ah = close file
  133.         INT     21H             ; .. ask DOS to do it
  134.  
  135. MAIN80:     MOV     AH, 4FH            ; ah = find next file
  136.         INT     21H             ; q. file found?
  137.         JNC     MAIN10            ; a. yes .. continue
  138.  
  139.             Mov     BX,BHandle              ;; Get back side file handle
  140.             Mov     AH,3Eh                  ;; AH = close file
  141.             Int     21h                     ;; Ask DOS to do it.
  142.  
  143.         MOV     DX, OFFSET DOLLAR        ; dx -> null message
  144.         CALL    DIE             ; .. say goodnight
  145.  
  146. MAIN        ENDP
  147. ; ---------------------------------------------------------------------------
  148. ;   INIT - Handle initialization
  149. ; ---------------------------------------------------------------------------
  150. INIT        PROC
  151.  
  152.         CLD                 ; assure ascending
  153.         MOV     AH, 19H            ; ah = get current drive
  154.         INT     21H             ; al = current drive
  155.         MOV     EDRV, AL            ; save entry drive
  156.  
  157.         MOV     SI, OFFSET EDIR        ; si -> current directory area
  158.         MOV     BYTE PTR [SI], '\'      ; .. start with backslash
  159.         INC     SI                ; si -> next byte
  160.         XOR     DL, DL            ; dl = default drive
  161.         MOV     AH, 47H            ; ah = get current dir
  162.         INT     21H             ; .. save in area
  163.  
  164.             Mov     DX,Offset BackFile      ;; Point to filename to create
  165.             Mov     AH,3Ch                  ;; DOS Create file call
  166.             Xor     CX,CX                   ;; File attributes (none)
  167.             Int     21h                     ;; Call DOS to do it.
  168.             Jnc     Init05                  ;; Continue if no error on create
  169.  
  170.             Mov     DX,Offset Backerr       ;; Point to error message
  171.             Call    Die                     ;; And bail out...
  172.  
  173. Init05:     Mov     BHandle,AX              ;; Save file handle
  174.  
  175.         MOV     DX, OFFSET HEADER_MSG   ; dx -> header message
  176.         MOV     AH, 9            ; ah = print ascii$ message
  177.         INT     21H             ; .. ask DOS to do it
  178.  
  179.         CALL    PARMS            ; check parameters
  180.  
  181.         CMP     ARG2, 0            ; q. arg2 specified?
  182.         JE        INIT20            ; a. yes .. skip open
  183.  
  184.         MOV     DX, ARG2            ; dx -> arg2 value
  185.         MOV     AH, 3CH            ; ah = create file
  186.         XOR     CX, CX            ; .. cx = file attributes
  187.         INT     21H             ; q. open the file ok?
  188.         JNC     INIT10            ; a. yes .. continue
  189.  
  190.         MOV     DX, OFFSET PRTOERR        ; dx -> open error message
  191.         CALL    DIE             ; .. you're dead, Jim.
  192.  
  193. INIT10:     MOV     PHANDLE, AX         ; save printer handle
  194.  
  195. INIT20:     CALL    DFLPATH            ; set up dir & drive
  196.  
  197.         MOV     AH, 4EH            ; ah = find first
  198.         MOV     DX, OFFSET FILENAME     ; dx -> file to find
  199.         XOR     CX, CX            ; cx = search attribute
  200.         INT     21H             ; q. find first file ok?
  201.         JNC     INIT90            ; a. yes .. continue
  202.  
  203.         MOV     DX, OFFSET FILENF        ; dx -> file not found
  204.         CALL    DIE             ; .. gasp you're final breath
  205.  
  206. INIT90:     RET                 ; return to caller
  207.  
  208. INIT        ENDP
  209. ; ---------------------------------------------------------------------------
  210. ;   OPEN - Opens the next file to process and update title line
  211. ;     Exit: Carry indicates file would not open.
  212. ; ---------------------------------------------------------------------------
  213. OPEN        PROC
  214.  
  215.         MOV     DX, OFFSET DTA_NAME     ; dx -> file name
  216.         MOV     AX, 3D00H            ; al = open for read
  217.         INT     21H             ; .. ask DOS to do it.
  218.         JNC     OPEN05            ; ok .. continue
  219.  
  220.         RET                 ; else .. return if error
  221.  
  222. OPEN05:     MOV     FHANDLE, AX         ; save file handle
  223.         MOV     LASTBUFF, 0         ; show last buffer not read
  224.  
  225.         MOV     SI, OFFSET DTA_NAME     ; si -> file name
  226.         MOV     DI, OFFSET TITLE_FLE    ; di -> file name area
  227.         PUSH    DI                ; .. save it
  228.         MOV     AL, ' '                 ; al = blank
  229.         MOV     CX, 15            ; .. amount to blank
  230.       REP   STOSB                ; .. clear the file name
  231.         POP     DI                ; .. restore output pointer
  232.  
  233. OPEN10:     LODSB                ; al = byte from file name
  234.  
  235.         OR        AL, AL            ; q. end of name?
  236.         JZ        OPEN20            ; a. yes .. end loop
  237.  
  238.         STOSB                ; store a byte
  239.         JMP     OPEN10            ; .. and move next
  240.  
  241. OPEN20:     MOV     BL, '0'                 ; fill value
  242.         MOV     AX, DS:DTA_DATE        ; ax = date field
  243.         PUSH    AX                ; save for later
  244.         PUSH    AX                ; .. again
  245.  
  246.         MOV     CL, 5            ; cl = shift value
  247.         SHR     AX, CL            ; .. mm to lower bits
  248.         AND     AX, 0FH            ; .. upper bits off
  249.         MOV     CX, 2            ; cx = number of characters
  250.         MOV     DI, OFFSET TITLE_DTE    ; di -> mm
  251.         CALL    ITOA            ; .. move in mm
  252.  
  253.         POP     AX                ; ax = date
  254.         AND     AX, 1FH            ; al = dd
  255.         MOV     CX, 2            ; cx = number of chars
  256.         MOV     DI, OFFSET TITLE_DTE+3  ; di -> dd
  257.         CALL    ITOA            ; .. move into dd
  258.  
  259.         POP     AX                ; ax = date
  260.         MOV     CL, 9            ; cl = shift amount
  261.         SHR     AX, CL            ; .. ax = yy
  262.         ADD     AX, 1980            ; ax = year
  263.         MOV     CX, 4            ; cx = length of output
  264.         MOV     DI, OFFSET TITLE_DTE+6  ; di -> yyyy
  265.         CALL    ITOA            ; .. move into yyyy
  266.  
  267.         MOV     AX, DS:DTA_TIME        ; ax = time
  268.         PUSH    AX                ; .. save for later
  269.         MOV     CL, 11            ; cl = shift value
  270.         SHR     AX, CL            ; .. ax = hh
  271.         MOV     CX, 2            ; cx = length of output
  272.         MOV     DI, OFFSET TITLE_TME    ; di -> hh
  273.         CALL    ITOA            ; .. move into hh
  274.  
  275.         POP     AX                ; ax = time
  276.         MOV     CL, 5            ; cl = shift value
  277.         SHR     AX, CL            ; ax = mm
  278.         AND     AX, 3FH            ; .. upper bits off
  279.         MOV     CX, 2            ; cx = length of output
  280.         MOV     DI, OFFSET TITLE_TME+3  ; di -> mm
  281.         CALL    ITOA            ; .. move into mm
  282.  
  283.         MOV     AH, 40H            ; ah = write to device
  284.         MOV     BX, 1            ; bx = stdout device
  285.         MOV     CX, TITLE_DSP        ; cx = length to display
  286.         MOV     DX, OFFSET TITLE_DTE    ; dx -> part of header line
  287.         INT     21H             ; issue dos call
  288.  
  289.         MOV     AH, 40H            ; ah = write to device
  290.         MOV     BX, 1            ; bx = stdout device
  291.         MOV     CX, 2            ; cx = length to display
  292.         MOV     DX, OFFSET CRLF        ; dx -> <cr><lf> string
  293.         INT     21H             ; issue dos call
  294.  
  295.         CLC                 ; show all went ok
  296. OPEN90:     RET
  297.  
  298. OPEN        ENDP
  299. ; ---------------------------------------------------------------------------
  300. ;   READ - Read the next buffer full
  301. ;     Exit: si -> next line, 0 if eof, cx =  length of line
  302. ; ---------------------------------------------------------------------------
  303. READ        PROC
  304.  
  305.         PUSH    AX                ; save registers
  306.         PUSH    BX
  307.         PUSH    DX
  308.  
  309.         MOV     SI, 0            ; si -> nothing
  310.  
  311.         CMP     LASTBUFF, 1         ; q. last buffer have 1ah?
  312.         JE        READ90            ; a. yes .. end it all
  313.  
  314.         MOV     AH, 03FH            ; ah = read file
  315.         MOV     BX, FHANDLE         ; bx = handle of file to read
  316.         MOV     CX, BUFLEN            ; cx = amount to read
  317.         MOV     DX, OFFSET BUFFER        ; dx -> buffer
  318.         INT     21H             ; read, please
  319.         JC        READ90            ; error .. return eof
  320.  
  321.         OR        AX, AX            ; q. any read?
  322.         JZ        READ90            ; a. yes .. return with something
  323.  
  324.         MOV     SI, OFFSET BUFFER        ; si -> start of line
  325.         MOV     CX, AX            ; cx = nbr of characters read
  326.         MOV     BX, AX            ; .. and bx
  327.  
  328.         MOV     DI, SI            ; di -> chars read
  329.         MOV     AL, 1AH            ; al = EOF indicator
  330.  
  331.     REPNE   SCASB                ; q. eof found?
  332.         JNE     READ80            ; a. no .. continue
  333.  
  334.         INC     CX                ; .. increment count
  335.         NEG     CX                ; .. and negate it
  336.         MOV     LASTBUFF, 1         ; .. and set lastbuff flag
  337.  
  338. READ80:     ADD     CX, BX            ; q. any bytes this buffer?
  339.         JNZ     READ90            ; a. yes .. continue
  340.  
  341.         MOV     SI, 0            ; a. else .. show end of file.
  342.  
  343. READ90:     POP     DX                ; restore registers
  344.         POP     BX                ;
  345.         POP     AX                ;
  346.         RET                 ; ..and return to caller
  347.  
  348. READ        ENDP
  349. ; ---------------------------------------------------------------------------
  350. ;   PRINT - Print requested data
  351. ;     Entry: si -> string to print or 0, cx =  length of input string
  352. ; ---------------------------------------------------------------------------
  353. PRINT        PROC
  354.  
  355.         OR        SI, SI            ; q. end of file call?
  356.         JNE     PRINT10            ; a. no .. continue
  357.  
  358.         CALL    EPILOGUE            ; put out trailing characters
  359.         RET                 ; ..and return to caller
  360.  
  361. PRINT10:    PUSH    AX                ; save registers
  362.         PUSH    BX
  363.         PUSH    CX
  364.         PUSH    DX
  365.         PUSH    SI
  366.  
  367.         CMP     HPSTATE, 0            ; q. initial state?
  368.         JNE     PRINT20            ; a. no .. continue
  369.  
  370.         CALL    PROLOGUE            ; send out initial string
  371.  
  372. PRINT20:    CALL    EXPAND            ; handle tab expansion
  373.         MOV     DX, SI            ; dx -> start of new buffer
  374.         MOV     BX, CX            ; bx = nbr of chars in buffer
  375.         XOR     CX, CX            ; cx = nbr of chars to print
  376.         MOV     AH, USEDLEN         ; ah = printed chars in this line
  377.  
  378. PRINT30:    LODSB                ; al = first character
  379.  
  380.         CMP     AL, 0CH            ; q. formfeed?
  381.         JNE     PRINT40            ; a. yes .. process it
  382.  
  383.         CALL    LINEPRT            ; print the line
  384.         CALL    PAGEBREAK            ; do a page break
  385.         XOR     AH, AH            ; ah = nbr of columns used
  386.         DEC     BX                ; bx = decrement remaining count
  387.         INC     DX                ; dx -> next printable character
  388.         JMP     PRINT70            ; ..and continue w/common code
  389.  
  390. PRINT40:    CMP     AL, 0AH            ; q. linefeed?
  391.         JNE     PRINT50            ; a. no .. continue
  392.  
  393.         DEC     BX                ; bx = remaining chars in buffer
  394.         INC     CX                ; cx = nbr of characters to print
  395.         CALL    LINEPRT            ; print the line
  396.         XOR     AH, AH            ; ah = nbr of columns used
  397.         CALL    BUMPLINE            ; increment/test line counter
  398.         JMP     PRINT70            ; ..and continue w/common code
  399.  
  400. PRINT50:    CMP     AL, 0DH            ; q. carriage return?
  401.         JNE     PRINT55            ; a. no .. continue
  402.         JMP     SHORT PRINT57        ; ..and continue w/common code
  403.  
  404. PRINT55:    CMP     AL, 08H            ; q. BackSpace?
  405.         JNE     PRINT60            ; a. no .. continue
  406.  
  407.         DEC     AH                ; move back a column
  408.         JNS     PRINT65            ; .. but not beyond first
  409.  
  410. PRINT57:    XOR     AH, AH            ; ah = start of line
  411.         JMP     SHORT PRINT65        ; .. and continue
  412.  
  413. PRINT60:    INC     AH                ; increment nbr of columns used
  414. PRINT65:    INC     CX                ; ..and nbr of chars to print
  415.         DEC     BX                ; decrement remaining char count
  416.  
  417.         CMP     AH, 81            ; q. reached end of line?
  418.         JL        PRINT70            ; a. no .. continue
  419.  
  420.         CALL    LINEPRT            ; print upto page width
  421.         PUSH    CX                ; save registers
  422.         PUSH    DX                ;
  423.         MOV     DX, OFFSET CRLF        ; dx -> <cr><lf>
  424.         MOV     CX, 2            ; cx = string length
  425.         CALL    WRITE            ; print the crlf to do line wrapping
  426.         POP     DX                ; restore registers
  427.         POP     CX                ;
  428.         XOR     AH, AH            ; ah = nbr of columns used
  429.         CALL    BUMPLINE            ; increment/test line counter
  430.  
  431. PRINT70:    OR        BX, BX            ; q. anything left to check?
  432.         JNZ     PRINT30            ; a. yes .. loop till done
  433.  
  434.         CALL    LINEPRT            ; print the line
  435.         MOV     USEDLEN, AH         ; save nbr of columns used
  436.  
  437.         POP     SI                ; restore registers
  438.         POP     DX                ;
  439.         POP     CX                ;
  440.         POP     BX                ;
  441.         POP     AX                ;
  442.         RET                 ; ..and return to caller
  443.  
  444. PRINT        ENDP
  445. ; ---------------------------------------------------------------------------
  446. ;   DIE - Display an error message and return to DOS
  447. ;     Entry: dx -> error message ended in dollar sign.
  448. ; ---------------------------------------------------------------------------
  449. DIE        PROC
  450.  
  451.         MOV     AH, 9            ; ah = print string
  452.         INT     21H             ; .. call dos to print error
  453.  
  454.         MOV     DL, EDRV            ; dl = drive to select
  455.         MOV     AH, 0EH            ; ah = select drive
  456.         INT     21H             ; .. select the drive
  457.  
  458.         MOV     DX, OFFSET EDIR        ; dx -> directory
  459.         MOV     AH, 3BH            ; ah = CHDIR request
  460.         INT     21H             ; .. ask DOS to do it
  461.  
  462.         MOV     AX, 4C00H            ; ax = exit
  463.         INT     21H             ; .. terminate routine
  464.  
  465. DIE        ENDP
  466. ; ---------------------------------------------------------------------------
  467. ;   PARMS - Parses the command line
  468. ; ---------------------------------------------------------------------------
  469. PARMS        PROC
  470.  
  471.         CALL    UPCASE            ; upper case the parm area
  472.         MOV     SI, 81H            ; si -> parms area
  473.  
  474. PARMS10:    LODSB                ; get parameter character
  475.  
  476.         CMP     AL, '/'                 ; q. option?
  477.         JE        PARMS80            ; a. yes .. check option
  478.         CMP     AL, 0DH            ; q. end of line?
  479.         JE        PARMS50            ; a. yes .. exit
  480.         CMP     AL, ' '                 ; q. blank?
  481.         JNA     PARMS10            ; a. yes .. skip
  482.         CALL    ARG             ; set the argument
  483.         JC        PARMSERR            ; .. die on an error
  484.  
  485. PARMS30:    LODSB                ; get next character
  486.         CMP     AL, 0DH            ; q. end of line?
  487.         JE        PARMS50            ; a. yes .. process
  488.         CMP     AL, '/'                 ; q. start of option?
  489.         JE        PARMS80            ; a. yes .. process
  490.         CMP     AL, ' '                 ; q. end of PARMS?
  491.         JA        PARMS30            ; a. no .. next char
  492.  
  493.         CALL    ENDPARM            ; terminate parm string
  494.         JMP     PARMS10            ; .. look for next
  495.  
  496. PARMS50:    CALL    ENDPARM            ; terminate parm string
  497.  
  498.         CMP     ARG1, 0            ; q. PARMS 1 available?
  499.         JE        PARMSERR            ; a. no .. error
  500.         RET                 ; .. else .. return to caller
  501.  
  502. PARMS80:    CALL    ENDPARM            ; terminate parm string
  503.         LODSB                ; al = option character
  504.  
  505.         CMP     AL, 'T'                 ; q. Tab width?
  506.         JNE     PARMSERR            ; a. no .. error in option
  507.  
  508.         CALL    ATOI            ; ax =  tab width
  509.  
  510.         CMP     AX, 16            ; q. request greater than max?
  511.         JG        PARMS10            ; a. yes .. unreasonable
  512.  
  513.         MOV     TABCOL, AX            ; .. save tab width
  514.         JMP     PARMS10            ; .. continue scan
  515.  
  516. PARMSERR:   MOV     DX, OFFSET FORMAT        ; dx -> format message
  517.         CALL    DIE             ; abort
  518.  
  519. PARMS        ENDP
  520. ; ---------------------------------------------------------------------------
  521. ;   ARG - Setup pointers to the command line arguments
  522. ;     Entry: si -> second character in argument.
  523. ;     Exit: ARG1 or ARG2 pointers filled in.
  524. ;    Carry set if more than 2 arguments detected.
  525. ; ---------------------------------------------------------------------------
  526. ARG        PROC
  527.  
  528.         LEA     BX, [SI-1]            ; bx -> argument
  529.         CMP     ARG1, 0            ; q. arg1 filled in?
  530.         JNE     ARG10            ; a. yes .. check 2
  531.         MOV     ARG1, BX            ; save arg1 pointer
  532.         JMP     SHORT ARG90         ; .. exit ok!
  533.  
  534. ARG10:        CMP     ARG2, 0            ; q. arg2 filled in?
  535.         JE        ARG20            ; a. no .. fill it in
  536.         STC                 ; else .. error
  537.         RET                 ; .. and return to caller
  538.  
  539. ARG20:        MOV     ARG2, BX            ; save arg2 pointer
  540. ARG90:        CLC                 ; show no error
  541.         RET                 ; return to caller
  542.  
  543. ARG        ENDP
  544. ; ---------------------------------------------------------------------------
  545. ;   ENDPARM - Handle parameters which end in a colon
  546. ;     Entry: si -> first character past end of parameter
  547. ; ---------------------------------------------------------------------------
  548. ENDPARM     PROC
  549.  
  550.         CMP     BYTE PTR [SI-2], ':'    ; q. argument end in a colon?
  551.         JNE     ENDPARM10            ; a. no .. continue
  552.  
  553.         MOV     BYTE PTR [SI-2], 0        ; ..it doesn't any more
  554.         RET                 ; ..and return
  555.  
  556. ENDPARM10:  MOV     BYTE PTR [SI-1], 0        ; end the parameter
  557.         RET                 ; ..and return
  558.  
  559. ENDPARM     ENDP
  560. ; ---------------------------------------------------------------------------
  561. ;   DFLPATH - Setup the default drive and path
  562. ; ---------------------------------------------------------------------------
  563. DFLPATH     PROC
  564.  
  565.         MOV     DI, ARG1            ; di -> first arg
  566.  
  567. DFLPATH10:  CMP     BYTE PTR [DI+1], ':'    ; q. drive specified?
  568.         JNE     DFLPATH20            ; a. no .. use current drive
  569.         MOV     DL, [DI]            ; dl = drive to use
  570.         SUB     DL, 'A'                 ; get requested drive number
  571.         MOV     AH, 0EH            ; set requested drive
  572.         INT     21H             ; .. via dos
  573.         ADD     DI, 2            ; di -> next part
  574.  
  575. DFLPATH20:  PUSH    DI                ; save pointer
  576.         MOV     BX, DI            ; bx -> start of area
  577.         XOR     AL, AL            ; al = search for null
  578.         MOV     CX, 128            ; very max to search
  579.         CLD
  580.     REPNE   SCASB                ; find end of arg
  581.         LEA     SI, [DI-1]            ; si -> nul
  582.         MOV     CX, 0            ; cx = # chars to move
  583.         CMP     SI, BX            ; q. any file name
  584.         JE        DFLPATH80            ; a. no .. error
  585.  
  586. DFLPATH30:  DEC     SI                ; si -> prev char
  587.         CMP     BYTE PTR [SI], '\'      ; q. dir?
  588.         JE        DFLPATH35            ; a. yes .. end of file name.
  589.         INC     CX                ; cx = char count
  590.         CMP     SI, BX            ; q. done?
  591.         JE        DFLPATH37            ; a. yes .. move file name
  592.         JMP     DFLPATH30            ; .. continue
  593.  
  594. DFLPATH35:  INC     SI                ; si -> start of file name
  595. DFLPATH37:  OR        CX, CX            ; q. file name spec'd?
  596.         JZ        DFLPATH80            ; a. no .. error
  597.         CMP     CX, 12            ; q. too long?
  598.         JA        DFLPATH85            ; a. yes .. error
  599.         PUSH    SI                ; save start pointer
  600.         MOV     DI, OFFSET FILENAME     ; di -> file name
  601.         INC     CX                ; .. assure nul moves too
  602.      REP    MOVSB                ; .. move in the file name
  603.         POP     SI                ; restore start pointer
  604.         POP     DI                ; .. and dir pointer
  605.         CMP     SI, BX            ; q. at start of parm?
  606.         JE        DFLPATH90            ; a. yes .. return
  607.         INC     BX                ; bx -> next char
  608.         CMP     SI, BX            ; q. root only given?
  609.         JE        DFLPATH40            ; a. yes .. continue
  610.         DEC     SI                ; si -> last \
  611.  
  612. DFLPATH40:  MOV     BYTE PTR [SI], 0        ; make dir ASCIIZ
  613. DFLPATH50:  MOV     DX, DI            ; dx -> directory
  614.         MOV     AH, 3BH            ; ah = CHDIR opcode
  615.         INT     21H             ; .. change directory
  616.         JNC     DFLPATH90            ; if ok .. continue
  617.         JMP     SHORT DFLPATH85        ; dx -> baddir request
  618.  
  619. DFLPATH80:  MOV     DX, OFFSET FORMAT        ; dx -> no file specified
  620.         CALL    DIE
  621.  
  622. DFLPATH85:  MOV     DX, OFFSET FILENF        ; dx -> invalid filename spec'd
  623.         CALL    DIE
  624.  
  625. DFLPATH90:  RET                 ; return to caller
  626.  
  627. DFLPATH     ENDP
  628. ; ---------------------------------------------------------------------------
  629. ;   EXPAND - Handle tab expansion
  630. ;     Entry:
  631. ;    si -> line read from file ended by a linefeed
  632. ;    cx =  length of line
  633. ;     Exit:
  634. ;    si -> reformatted line in output buffer
  635. ;    cx =  new line length
  636. ; ---------------------------------------------------------------------------
  637. EXPAND        PROC
  638.  
  639.         PUSH    AX                ; save registers
  640.         PUSH    BX
  641.         PUSH    DX
  642.         PUSH    DI
  643.  
  644.         MOV     DI, OFFSET OBUFF        ; di -> start of output buffer
  645.  
  646. EXPAND10:   LODSB                ; al = character from input line
  647.  
  648.         CMP     AL, 09H            ; q. tab character?
  649.         JNE     EXPAND30            ; a. no .. continue processing
  650.  
  651.         MOV     AX, CURCOL            ; ax = current column
  652.         DEC     AX                ; ax = column offset
  653.         XOR     DX, DX            ; dx:ax = current column
  654.         MOV     BX, TABCOL            ; bx = nbr of columns per tab
  655.         IDIV    BX                ; dx = space within tab stop
  656.  
  657.         SUB     BX, DX            ; bx = spaces left in tab stop
  658.  
  659.         MOV     AL, 20H            ; al = space char to padding string
  660.  
  661. EXPAND20:   STOSB                ; put a blank in output buffer
  662.         INC     CURCOL            ; bump current column nbr
  663.  
  664.         DEC     BX                ; q. done yet?
  665.         JNZ     EXPAND20            ; a. no .. keep looping
  666.         JMP     SHORT EXPAND50        ; a. yes .. get next character
  667.  
  668. EXPAND30:   CMP     AL, 0DH            ; q. carriage return?
  669.         JE        EXPAND33            ; a. yes .. reset column
  670.  
  671.         CMP     AL, 0CH            ; q. form feed?
  672.         JNE     EXPAND35            ; a. no .. continue processing
  673.  
  674. EXPAND33:   MOV     CURCOL, 0            ; setup for start of new line
  675.         JMP     SHORT EXPAND40        ; .. continue
  676.  
  677. EXPAND35:   CMP     AL, 08H            ; q. backspace?
  678.         JNE     EXPAND40            ; a. no .. continue
  679.  
  680.         STOSB                ; save the BS
  681.         DEC     CURCOL            ; .. move back a space
  682.         JNZ     EXPAND50            ; .. get next character
  683.  
  684.         MOV     CURCOL, 1            ; init current column
  685.         JMP     SHORT EXPAND50        ; .. continue
  686.  
  687. EXPAND40:   STOSB                ; move character to output line
  688.         CMP     AL, 0AH            ; q. line feed?
  689.         JE        EXPAND50            ; a. yes .. don't count it
  690.  
  691.         INC     CURCOL            ; bump current column nbr
  692.  
  693. EXPAND50:   LOOP    EXPAND10            ; ..loop till input exhausted
  694.  
  695.         MOV     SI, OFFSET OBUFF        ; si -> start of output buffer
  696.         MOV     CX, DI            ; di -> just past last char of output
  697.         SUB     CX, SI            ; cx = nbr of characters in output
  698.  
  699.         POP     DI                ; restore registers
  700.         POP     DX
  701.         POP     BX
  702.         POP     AX
  703.         RET                 ; ..and return to caller
  704.  
  705. EXPAND        ENDP
  706. ; ---------------------------------------------------------------------------
  707. ;   LINEPRT - Handle printing a line
  708. ;     Entry:
  709. ;    dx -> start of line
  710. ;    cx =  nbr of characters to print
  711. ;     Exit:
  712. ;    dx -> start of next line
  713. ;    cx =  0
  714. ; ---------------------------------------------------------------------------
  715. LINEPRT     PROC
  716.  
  717.         JCXZ    LINEPRT90            ; if nothing to print.. return
  718.  
  719.         CMP     NEWPAGE, 1            ; q. need a new page?
  720.         JNE     LINEPRT10            ; a. no .. continue
  721.  
  722.         CALL    PAGEBREAK            ; else .. do a pagebreak
  723.  
  724. LINEPRT10:  CALL    WRITE            ; write the line
  725.  
  726.         ADD     DX, CX            ; dx -> start of next line
  727.         XOR     CX, CX            ; cx = nbr of characters to print
  728. LINEPRT90:  RET
  729.  
  730. LINEPRT     ENDP
  731. ; ---------------------------------------------------------------------------
  732. ;   MKTITLE - Make the title line be ready to print
  733. ;     Exit:
  734. ;    dx -> title line
  735. ;    cx =  title line length
  736. ; ---------------------------------------------------------------------------
  737. MKTITLE     PROC
  738.         PUSH    AX                ; save registers
  739.         PUSH    BX
  740.         PUSH    DI
  741.  
  742.         MOV     AX, PAGENO            ; ax = page number
  743.         MOV     CX, 4            ; cx = length of output
  744.         MOV     BL, ' '                 ; bl = fill char (blank)
  745.         MOV     DI, OFFSET TITLE_PGE    ; di -> output area
  746.         CALL    ITOA            ; .. fill in page number
  747.  
  748.         MOV     DX, OFFSET TITLE_        ; dx -> title
  749.         MOV     CX, TITLE_LEN        ; cx = length of title
  750.         CALL    WRITE            ; print title line
  751.  
  752.         POP     DI                ; restore registers
  753.         POP     BX
  754.         POP     AX
  755.         RET                 ; return to caller
  756.  
  757. MKTITLE     ENDP
  758. ; ---------------------------------------------------------------------------
  759. ;   PAGEBREAK - Handle page overflow condition
  760. ; ---------------------------------------------------------------------------
  761. PAGEBREAK   PROC
  762.  
  763.             Push    AX                      ; save registers
  764.         PUSH    BX                ;
  765.         PUSH    CX                      ;
  766.         PUSH    DX                      ;
  767.  
  768.         TEST    PAGENO, 1            ; q. finishing up with left page?
  769.         JZ        PAGEBRK20            ; a. no .. do other page
  770.  
  771.         MOV     DX, OFFSET STRING3        ; dx -> get to right page string
  772.         MOV     CX, STRING3_LEN        ; cx = length
  773.         CALL    WRITE            ; write out 1st part of string
  774.  
  775.         MOV     BX, 66            ; bx = loop count
  776.         MOV     CX, 3            ; cx = nbr of chars to print
  777.         MOV     DX, OFFSET STRING4        ; dx -> vertical bar string
  778.  
  779. PAGEBRK10:  CALL    WRITE            ; write on line of vertical bars
  780.  
  781.         DEC     BX                ; q. done yet?
  782.         JNZ     PAGEBRK10            ; a. no .. keep looping
  783.  
  784.         MOV     DX, OFFSET STRING5        ; dx -> string to finish up
  785.         MOV     CX, STRING5_LEN        ; cx = length
  786.             Call    Write                   ;; Output it...
  787.         JMP     PAGEBRK30            ; ..and continue w/common code
  788.  
  789. PAGEBRK20:
  790.  
  791.             Mov     AX,CHandle              ;; Get current handle
  792.             Xchg    AX,NHandle              ;; Get next handle
  793.             Mov     CHandle,AX              ;; Swap current handle
  794.  
  795.             MOV     DX, OFFSET STRING6        ; dx -> get to left page string
  796.         MOV     CX, STRING6_LEN        ; cx = length
  797.             CALL    WRITE            ; print the init line
  798.             Mov     AL,0Ch                  ;; Get a formfeed
  799.             Mov     String6,AL              ;; Don't want FF on first pass
  800.  
  801. Pagebrk30:  MOV     LINECNT, 1            ; reset line counter
  802.         MOV     NEWPAGE, 0            ; clear new page request flag
  803.         INC     PAGENO            ; ..and bump page number
  804.  
  805.         CALL    MKTITLE            ; print title line
  806.  
  807.         POP     DX                ; restore registers
  808.         POP     CX                ;
  809.         POP     BX                ;
  810.             Pop     AX                      ;
  811.         RET                 ; ..and return to caller
  812.  
  813. PAGEBREAK   ENDP
  814. ; ---------------------------------------------------------------------------
  815. ;   BUMPLINE - Increment line counter and test for overflow
  816. ; ---------------------------------------------------------------------------
  817. BUMPLINE    PROC
  818.         INC     LINECNT            ; increment line counter
  819.  
  820.         CMP     LINECNT, 66         ; q. reached max lines/page?
  821.         JLE     BUMPLINE90            ; a. no .. continue
  822.  
  823.         MOV     NEWPAGE, 1            ; else .. show we'll need a new one
  824.  
  825. BUMPLINE90: RET                 ; ..then return to caller
  826.  
  827. BUMPLINE    ENDP
  828. ; ---------------------------------------------------------------------------
  829. ;   PROLOGUE - Put out laserjet initialization string
  830. ; ---------------------------------------------------------------------------
  831. PROLOGUE    PROC
  832.  
  833.         PUSH    CX                ; save registers
  834.         PUSH    DX
  835. ;
  836. ; The initialization string is first sent to the back side file, then to 
  837. ; the printer.  The handles are set up so the next handle to be used (NHandle)
  838. ; points to the back side file, and after the initialization string is sent
  839. ; to the printer with the second call, the current handle (CHandle) points
  840. ; to the printer.  After each physical page is printed, the two handles are
  841. ; swapped.  The Write subroutine writes to whichever file is pointed to by
  842. ; Chandle.
  843. ;
  844.             Mov     AX,BHandle              ;; Get pointer to back side file
  845.             Mov     CHandle,AX              ;; Point to back side file
  846.             Mov     NHandle,AX              ;; Also save as next handle to use
  847.         MOV     DX, OFFSET STRING1        ; dx -> initialization string
  848.         MOV     CX, STRING1_LEN        ; cx = length
  849.         CALL    WRITE            ; print the init line
  850.  
  851.             Mov     AX,PHandle              ;; Point to Printer
  852.             Mov     CHandle,AX              ;; Save as current handle
  853.             Mov     CX,String1_Len          ;; CX = Length
  854.             Mov     DX,Offset String1       ;; DX -> Initialization string
  855.             Call    Write                   ;; And send to printer
  856.  
  857.         MOV     PAGENO, 1            ; setup page number
  858.         MOV     CURCOL, 1            ; ..and current column number
  859.         MOV     LINECNT, 1            ; ..and line counter
  860.         MOV     HPSTATE, 1            ; ..show in left page
  861.         MOV     USEDLEN, 0            ; ..clear column position
  862.         CALL    MKTITLE            ; print title line
  863.  
  864.         POP     DX                ; restore registers
  865.         POP     CX                ;
  866.         RET                 ; ..and return to caller
  867.  
  868. PROLOGUE    ENDP
  869. ; ---------------------------------------------------------------------------
  870. ;   EPILOGUE - Put out laserjet finish up string
  871. ; ---------------------------------------------------------------------------
  872. EPILOGUE    PROC
  873.  
  874.             Push    AX                      ; save registers
  875.             Push    BX                      ;
  876.         PUSH    CX                ;
  877.         PUSH    DX                      ;
  878.  
  879. ;
  880. ; Calculate how many formfeeds we need at the end of the back side file.
  881. ;
  882.             Mov     AX,BHandle              ;; Point to back side file
  883.             Mov     CHandle,AX              ;; Make current output file
  884.             Mov     BX,1                    ;; Only one formfeed needed
  885.             Mov     AX,PageNo               ;; Get last page number
  886.             Cmp     AX,1                    ;; Have we only printed 1 pg?
  887.             Je      Epil10                  ;; Only need 1 formfeed
  888.             Inc     AX                      ;; Add 1
  889.             Shr     AX,1                    ;; Divide by 2
  890.             Test    AX,1                    ;; Is physical page odd?
  891.             Jz      Epil10                  ;; No - page is even
  892.             Inc     BX                      ;; Page is odd - 2 formfeeds
  893.  
  894. Epil10:        MOV     DX, OFFSET STRING2        ; dx -> termination string
  895.         MOV     CX, STRING2_LEN        ; cx = length
  896.         CALL    WRITE            ; print the init line
  897.             Dec     BX                      ;; Need any more?
  898.             Jnz     Epil10                  ;; Continue as needed
  899. ;
  900. ; Now send the reset string to the printer itself.
  901. ;
  902.             Mov     AX,PHandle              ;; Point to the printer
  903.             Mov     CHandle,AX              ;; Make it current
  904.             Mov     DX,Offset String2       ;; DX -> termination string
  905.             Mov     CX,String2_len          ;; CX = length
  906.             Call    Write                   ;; And send it.
  907.  
  908.             Mov     String6,0Dh             ;; Don't want FF on first pass
  909.  
  910.         MOV     HPSTATE, 0            ; show back to initialization state
  911.  
  912.         POP     DX                ; restore registers
  913.         POP     CX                ;
  914.             Pop     BX                      ;
  915.             Pop     AX                      ;
  916.  
  917.         RET                 ; ..and return to caller
  918.  
  919. EPILOGUE    ENDP
  920. ; ---------------------------------------------------------------------------
  921. ;   WRITE - Send a string to the printer
  922. ;     Entry:
  923. ;    dx -> string to write
  924. ;    cx =  nbr of characters
  925. ; ---------------------------------------------------------------------------
  926. WRITE        PROC
  927.  
  928.         PUSH    AX                ; save registers
  929.         PUSH    BX
  930.  
  931.         MOV     AH, 40H            ; ah = write to file/device function
  932.         MOV     BX, CHANDLE         ; bx = printer handle
  933.         INT     21H             ; issue dos call
  934.  
  935.         POP     BX                ; restore registers
  936.         POP     AX                ;
  937.         RET                 ; ..and return to caller
  938.  
  939. WRITE        ENDP
  940. ; ---------------------------------------------------------------------------
  941. ;   UPCASE - Convert command line arguments to uppercase
  942. ; ---------------------------------------------------------------------------
  943. UPCASE        PROC
  944.  
  945.         PUSH    SI                ; save caller regs
  946.         PUSH    DI
  947.         MOV     SI, 81H            ; si -> start of parm area
  948.         MOV     DI, SI            ; .. same for di
  949.         CLD                 ; .. assure ascending
  950.  
  951. UPCASE10:   LODSB                ; al = char
  952.         CMP     AL, 0DH            ; q. end of line?
  953.         JE        UPCASE90            ; a. yes .. end of line!
  954.         CMP     AL, 'a'                 ; q. is it below 'a'?
  955.         JB        UPCASE20            ; a. yes .. continue
  956.         CMP     AL, 'z'                 ; q. is it above 'z'?
  957.         JA        UPCASE20            ; a. yes .. continue
  958.         SUB     AL, 20H            ; set to upper case
  959.  
  960. UPCASE20:   STOSB                ; save the byte
  961.         JMP     UPCASE10            ; .. and continue
  962.  
  963. UPCASE90:   POP     DI                ; restore caller regs
  964.         POP     SI
  965.         RET                 ; .. and return to caller
  966.  
  967. UPCASE        ENDP
  968. ; ---------------------------------------------------------------------------
  969. ;   ATOI - Translate an ascii value to binary
  970. ;     Entry:
  971. ;    si -> ascii value
  972. ;     Exit:
  973. ;    al =  binary value
  974. ; ---------------------------------------------------------------------------
  975. ATOI        PROC
  976.  
  977.         XOR     AX, AX            ; ax = accumulator = 0
  978.  
  979. ATOI10:     CMP     BYTE PTR [SI], '0'      ; q. below ascii 0?
  980.         JB        ATOI90            ; a. yes.. exit
  981.  
  982.         CMP     BYTE PTR [SI], '9'      ; q. above ascii 9?
  983.         JA        ATOI90            ; a. yes.. exit
  984.  
  985.         XOR     AH, AH            ; reset ah
  986.         MOV     BL, 10            ; bl = multiply value
  987.         MUL     BL                ; .. multiply by 10
  988.         MOV     BL, [SI]            ; bl = value
  989.         AND     BL, 0FH            ; .. upper bits off
  990.         ADD     AL, BL            ; .. add to bl
  991.  
  992.         INC     SI                ; si -> next char
  993.         JMP     ATOI10            ; .. tranlate it
  994.  
  995. ATOI90:     RET                 ; .. return to caller
  996.  
  997. ATOI        ENDP
  998. ; ---------------------------------------------------------------------------
  999. ;   ITOA - Integer to ASCII characters
  1000. ;     Entry:
  1001. ;    ax =  value to convert
  1002. ;    bl =  fill character
  1003. ;    cx =  nbr of characters
  1004. ;    di -> start of alpha area
  1005. ; ---------------------------------------------------------------------------
  1006. ITOA        PROC
  1007.  
  1008.         PUSH    AX                ; save registers
  1009.         PUSH    BX
  1010.         PUSH    CX
  1011.         PUSH    DX
  1012.         PUSH    DI
  1013.         PUSHF
  1014.         STD                 ; ..and set direction flag
  1015.  
  1016.         ADD     DI, CX            ; di -> 1st char past work area
  1017.         DEC     DI                ; di -> last char in work area
  1018.         PUSH    BX                ; save fill character
  1019.         MOV     BX, 10            ; bx = divisor
  1020.  
  1021. ITOA10:     OR        AX, AX            ; q. any value to convert?
  1022.         JZ        ITOA20            ; a. no .. exit loop
  1023.  
  1024.         XOR     DX, DX            ; dx:ax = value to divide
  1025.         IDIV    BX                ; ax = dividend, dx = remainder
  1026.         OR        DL, 30H            ; dl = ASCII number
  1027.         MOV     [DI], DL            ; store character in buffer
  1028.         DEC     DI                ; di -> next output char location
  1029.  
  1030.         DEC     CX                ; q. any more room in buffer?
  1031.         JNZ     ITOA10            ; a. yes .. continue loop
  1032.  
  1033.         POP     BX                ; restore register
  1034.         JMP     ITOA90            ; ..and exit through common code
  1035.  
  1036. ITOA20:     POP     AX                ; al = fill character
  1037.  
  1038. ITOA30:     STOSB                ; store fill character
  1039.  
  1040.         DEC     CX                ; q. any more room in buffer?
  1041.         JNZ     ITOA30            ; a. yes .. continue loop
  1042.  
  1043. ITOA90:     POPF                ; restore flags
  1044.         POP     DI                ; ..and registers
  1045.         POP     DX                ;
  1046.         POP     CX                ;
  1047.         POP     BX                ;
  1048.         POP     AX                ;
  1049.         RET                 ; ..and return
  1050.  
  1051. ITOA        ENDP
  1052. ; ---------------------------------------------------------------------------
  1053. ;   Uninitialized data areas
  1054. ; ---------------------------------------------------------------------------
  1055. UDATA        EQU     $                ; start of unitialized data
  1056. PAGENO        EQU     WORD PTR UDATA        ; current page number
  1057. CURCOL        EQU     WORD PTR PAGENO+2        ; current column
  1058. LINECNT     EQU     WORD PTR CURCOL+2        ; line count
  1059. EDRV        EQU     BYTE PTR LINECNT+2        ; current disk
  1060. EDIR        EQU     BYTE PTR EDRV+1        ; current directory
  1061. FILENAME    EQU     BYTE PTR EDIR+65        ; filename specifed as ARG1
  1062. LASTBUFF    EQU     BYTE PTR FILENAME+13    ; last buffer indicator
  1063. FHANDLE     EQU     WORD PTR LASTBUFF+1     ; input file handle
  1064. BUFFER        EQU     BYTE PTR FHANDLE+2        ; file buffer
  1065. BUFLEN        EQU     2048            ; length of buffer
  1066. USEDLEN     EQU     BYTE PTR BUFFER+BUFLEN  ; used length in a logical line
  1067. OBUFF        EQU     BYTE PTR USEDLEN+1        ; output buffer - must be last!
  1068.  
  1069. CSEG        ENDS                ; end of code segment
  1070.         END     START
  1071.