 name XPRT
 page 62,128
 title XPRT -- Print a File

;XPRT -- a utility to print out text files with titles and page numbers
;on the current list device.  The high bit of all characters is stripped
;so that raw WordStar or other word processing files can be listed.
;That is, unless the /X (Translate) option is specified, then the
;special characters (>128) are translated to GEMINI STAR compatable
;format.  This should be generalized but it will do what I want.
;This translate is intended to convert files formatted for the screen
;or IBM graphics to Gemini compatability ... should work for most cases.
;Embeded form feeds codes are recognized, and tabs are expanded.
;Unknown control codes (such as the ^B and ^U codes found in WordStar
;documents) are discarded.
;
;XPRT has been designed to work with the Gemini Start 10X printer.
;Some functions should also work on EPSON printers.  Specifically,
;the basic XPRT operation is OK and the /C and /N options should
;work (but not /I, /E, /8).  Full compatability with EPSON
;will require modification of this program.
;
;This program is desinged to operate as a COM file under PC-DOS.
;It has been tested with PC-DOS 3.1 on an IBM XT.


;Used in the form:
;      A>XPRT path\filename.ext  [/S] [/8] [/f=3] [/I] [/N] ["title text"]
;             (items in brackets are optional)
;               /T -- output set to terminal (the console or screen)
;               /C -- set COPY option
;               /6 -- set 6 lines/inch spacing
;               /8 -- set 8 lines/inch spacing
;               /f=1 -- 10cpi
;               /f=2 -- 12cpi
;               /f=3 -- 15cpi
;               /f=4 -- 17cpi
;               /f=5 -- 20cpi
;               /S -- strip high order bits from input.
;               /X -- set Gemini Translate of special characters
;               /I -- set indent
;               /N -- add sequence numbers
;               /z -- suppress eof (1ah) check -- read until len=0
;               /d=1 -- Epson
;               /d=2 -- Gemini Star 10x
;               /d=3 -- NEC P6/p7
;               /d=4 -- IBM ProPrinter

;NOTE ---
;    1. This program requires PC-DOS 2.0 or later.
;    2. The following applies to the original LIST program:
;       Version 1.0 February 28, 1984
;       Copyright (c) 1984 by Ray Duncan
;       May be freely reproduced for noncommercial use.


;STATUS --
;      Updated and extensively modified by Gene Czarcinski
;      ... This is based on Ray Duncan's LIST program.
;
;      Version 2.3, Gene Czarcinski,  October 10, 1984 - created
;      Version 2.4, Gene Czarcinski,  December 3, 1984 - updated
;        ... add help ('?') facility
;        ... default title is the filename
;        ... suppress leading formfeed
;      Version 2.5, Gene Czarcinski, May 24, 1986 - updated
;        ... add /X option
;        ... fix read_block to handle file with no ^Z correctly
;        ... no final ff if output to terminal
;      Version 2.6, Gene Czarcinski, June 8, 1986 - updated
;        ... support PICA, ELITE and COMPRESSED char sets
;        ... no RESET .. init printer each time
;      Version 2.7, Gene Czarcinski, June 9, 1986 - updated
;        ... finish /N support
;        ... misc. cleanup
;      Version 3.0, Gene Czarcinski, February 15, 1987 -
;        ... renamed from LIST to XPRT
;        ... add /S to strip high order bits from input.
;        ... add translate (/X) option
;      Version 4.0, Gene Czarcinski, September 28, 1987 - updated
;        ... add multi printer type support (especially NEC p6)
;        ... add capability to just copy input (with printer control)
;        ... change parm analysis: can be option groups and allow
;            anywhere in command-line input string ... the slash (/) is
;            still the only option specifier
;        ... fixup specifying command -- MASM 5.0
;        ... optionally suppress EOF (1ah) check


cr      equ     0dh             ;ASCII CR
lf      equ     0ah             ;ASCII LF
ff      equ     0ch             ;ASCII FormFeed
eof     equ     01ah            ;end-of-file marker
tab     equ     09h             ;ASCII tab char

blksize equ     1024            ;size of block reads from input file
linesize equ    250             ;max length of output line
heading_lines equ 3             ;number of lines in page heading

console_handle equ 1            ;handle of standard console device
error_handle   equ 2            ;not re-directable...std error output
list_handle    equ 4            ;handle of standard list device

;----------------------------------------------------------------------------

xprt    segment para public 'CODE'

        assume cs:xprt,ds:xprt,es:xprt

        org     0080h           ; location of command tail
command LABEL   BYTE            ;buffer for command tail

        org     0100h

main    proc    far             ;entry point from PC-DOS
        jmp     starts
;----------------------------------------------------------------------------

printer_type    db      3       ;0=none (screen)
                                ;1=Epson FX
                                ;2=Gemini Star 10x
                                ;3=NEC p6/p7
                                ;4=IBM Proprinter

flg_font        db      1       ;font type:
                                ; 1=10cpi, 2=12cpi, 3=15cpi, 4=17cpi, 5=20cpi
flg_lpi         db      6       ;lines per inch
flg_indent      db      0       ;indenting flag
flg_copy        db      0       ; Copy Option
flg_no_eof      db      0       ; eof skip check

input_name      db      64 dup (0)      ;buffer for input filespec
input_handle    dw      0               ;token from PC-DOS for input file
output_handle   dw      list_handle     ;the handle of the output file
input_ptr       dw      0               ;pntr to input  buffer
output_ptr      dw      0               ;pntr to output buffer
column          dw      0               ;column count for tab processing
pagesize        dw      60              ;lines/page
linenumber      dw      0               ;for /N
linecount       dw      99              ;line counter for current page ...
                                        ;init to pagesize to force eject
pagecount       dw      0               ;current page number
titlecount      db      0               ;count for scanning title
term_switch     dw      0               ;set to -1 if /T
xlate_switch    dw      0               ;set to -1 if /X
strip_switch    dw      0               ;set to -1 if /S
num_switch      dw      0               ;set to -1 if /N
ttl_flag        dw      0               ;set to -1 if title from command line

init_printer    db      32 dup (0)      ;set by set_option
init_printer_length dw 0

msg1            db      cr,lf,'Cannot find INPUT file.',cr,lf,'$'
msg2            db      cr,lf,'Missing filename.',cr,lf,'$'
helpmsg db      cr,lf,'---XPRT Version 4.0, September 28, 1987---'
 db cr,lf,cr,lf
 db 'XPRT <path\filename.ext> [/t] [/n] [/i] ... "..title.."'
 db cr,lf
 db cr,lf,'  /c - plain COPY option .. no pagination'
 db cr,lf,'  /t - set output to terminal/screen'
 db cr,lf,'  /f=n font select .. n selects cpi value'
 db cr,lf,'     n=1 -- 10cpi (default)   n=4 -- 17cpi'
 db cr,lf,'     n=2 -- 12cpi             n=5 -- 20cpi'
 db cr,lf,'     n=3 -- 15cpi'
 db cr,lf,'  /6 - set 6 lines/inch'
 db cr,lf,'  /8 - set 8 lines/inch'
 db cr,lf,'  /i - set printer indent mode'
 db cr,lf,'  /s - strip input'
 db cr,lf,'  /z - skip eof check'
 db cr,lf,'  /x - set translate mode'
 db cr,lf,'  /n - sequence number the output lines'
 db cr,lf,'  /d=n - set output printer type'
 db cr,lf,'     n=1 Epson              n=3 NEC P6/P7'
 db cr,lf,'     n=2 Gemini Star 10x    n=4 IBM Proprinter'
 db cr,lf
helplen equ     $-helpmsg

help_pt db cr,lf,'Printer Type: '
help_ptl equ $-help_pt
help_pt0 db 'None'
help_pt0l equ $-help_pt0
help_pt1 db 'Epson FX'
help_pt1l equ $-help_pt1
help_pt2 db 'Gemini Star 10x'
help_pt2l equ $-help_pt2
help_pt3 db 'NEC P6/P7'
help_pt3l equ $-help_pt3
help_pt4 db 'IBM Proprinter'
help_pt4l equ $-help_pt4
help_ptx db cr,lf
help_ptxl equ $-help_ptx

;       0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
Xtbl db 000,001,002,003,004,005,006,007,008,009,010,011,012,013,014,015 ;00
     db 016,017,018,019,020,021,022,023,024,025,026,027,028,029,030,031 ;10
     db 032,032,032,032,032,032,032,032,032,032,032,032,032,032,032,032 ;20
     db 032,032,032,032,032,032,032,032,032,032,032,032,032,032,032,032 ;30
     db 032,032,032,032,032,032,032,032,032,032,032,032,032,032,032,032 ;40
     db 032,032,032,032,032,032,032,032,032,032,032,032,032,032,032,032 ;50
     db 032,032,032,032,032,032,032,032,032,032,032,032,032,032,032,032 ;60
     db 032,032,032,032,032,032,032,032,032,032,032,032,032,032,032,032 ;70
     db 239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239 ;80*
     db 239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239 ;90*
     db 239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239 ;A0*
     db 20h,20h,20h,245,249,249,249,242,242,249,245,242,247,247,247,242 ;B0*
     db 246,248,243,244,241,250,244,244,246,240,248,243,244,241,250,248 ;C0*
     db 248,243,243,246,246,240,240,250,250,247,240,239,231,233,234,232 ;D0*
     db 20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h ;E0*
     db 20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,20h,174,20h ;F0*


input_buffer_len dw     0               ;length read
input_buffer    db      blksize dup (?) ;deblocking buffer for input file
output_number   db      'nnnnn>'
output_buffer   db      linesize dup (?); output buffer for list device

heading_buffer  db      00              ;initial=null, then formfeed
heading_month   db      '00/'
heading_day     db      '00/'
heading_year    db      '00  '
heading_hh      db      '00.'
heading_mm      db      '00  '
heading1        db      40 dup (' ')    ;filled in with user's title
max_title       equ     $-heading1
                db      '  '
                db      '       Page '
heading2        db      '_____',cr
                db      heading_lines dup (lf)
heading_length  equ     $-heading_buffer

;-------Main Line Code-------------------------------------------------------

starts: push    ds              ;save DS:0000 for final
        xor     ax,ax           ;return to PC-DOS
        push    ax

        call    get_date        ;insert formatted date/time into title
        call    get_title       ;get maining title from command line tail
        call    get_option      ;process (switch) options
        call    get_filename    ;get path anbd file spec. for input file
                                ;from the command line tail.
        mov     ax,es           ;set DS=ES for remainder of pgm
        mov     ds,ax

        jnc     main15          ;jump, got accesptable name
        mov     dx,offset msg2  ;missing or illegal filespec
        jmp     main9           ;print error msg and exit

main15: mov     al,input_name   ;check if help wanted
        cmp     al,'?'
        jne     main19          ;continue
        call    display_info
        ret                     ;return to DOS

main19: call    open_input      ;now try to open the inpuyt file
        jnc     main2           ;jump if opened OK
        mov     dx,offset msg1  ;open failed for input file
        jmp     main9           ;print error msg and exit

main2:  call    set_option

        cmp     term_switch,0   ;console (/s) or printer ?
        je      main22          ;printer

        mov     ax,console_handle ; init for console
        mov     output_handle,ax
        mov     al,0            ;if console, set formfeed to null
        mov     heading_buffer,al
        jmp     main25          ;skip printer init code

main22: mov     dx,offset init_printer
        mov     cx,init_printer_length
        mov     bx,output_handle
        mov     ah,40h
        int     21h

main25:                         ;initialize input deblocking buffer
        call    read_block      ;get first block
        mov     output_ptr,0    ;set output to null
        mov     linenumber,0
        cmp     input_buffer_len,0
        jne     main3
        jmp     main8

main3:                          ;file successfully opened.
                                ;now print it.
        call    get_char        ;read 1 char from input
        cmp     al,20h          ;is it a control code?
        jae     main4           ;no, write it to main device.
                                ;yes, it is a control code
        cmp     al,eof          ;is it e-o-f marker?
        je      main8           ;yes, go close files
        cmp     al,tab          ;is it a tab char?
        je      main5           ;yes, go to special processing.
        cmp     al,ff           ;us it a FormFeed?
        je      main54          ;yes, goto special processing
        cmp     al,cr           ;if it is an illegal control code,
        jne     main3           ;discard it and get next char.
        mov     al,lf           ;insert a line feed
        call    put_char

        mov     al,cr           ;restore reg
        call    put_char

        mov     column,0        ;if C/R, store it into output
        jmp     main53          ;string and initialize column output.

main4:  inc     column          ;count chars sent on this line.

main45: call    put_char        ;write this char into forming output string.

        cmp     output_ptr,linesize-1  ;about to overflow?
        je      main53          ;yes,force print to buffer.
        jmp     main3           ;no,get next char

main5:  mov     ax,column       ;process tab char .. let DX:AX=column count
        cwd
        mov     cx,8            ;divide by 8
        idiv    cx
        sub     cx,dx           ;remainder is in DX
        add     column,cx       ;update column pntr
main51:                         ;8 minus the remainder.
        push    cx              ;gives the number of spaces
        mov     al,20h          ;to send out to move to
        call    put_char        ;the next tyab position.
        pop     cx              ;restore space count
        loop    main51
        jmp     short main3     ;get next char


main53:                 ;line-feed detected, interprete as print command.
        call    heading_maybe   ;print heading if needed.
        call    write_line      ;print output buffer
        jmp     main3           ;continue

main54:                         ;handle a form-feed
        call    write_maybe     ;FormFeed detected ..
                                ;if anything waiting in output buffer,
                                ;print it first.
        call    print_heading   ;new page and print title
        jmp     main3           ;continue

main8:                          ;end-of-file detected
        call    write_maybe     ;print if anything waiting ...

main81: cmp     term_switch,0   ;Console output?
        jne     main83          ;yes, skip ff
        mov     al,ff           ;send FormFeed to finish maining
        call    put_char
        call    write_line
main83: mov     bx,input_handle ;BX=handle --- close the input file
        mov     ah,3eh          ;close
        int     21h
main85: ret                     ;return to PC-DOS

main9:                  ;come here to print error message
        mov     ah,9            ;and return to dos
        int     21h
        ret

main    endp

display_info proc near          ;display some help info
        mov     dx,offset helpmsg
        mov     cx,helplen
        mov     bx,console_handle
        mov     ah,40h
        int     21h
        mov     dx,offset help_pt
        mov     cx,help_ptl
        mov     bx,console_handle
        mov     ah,40h
        int     21h
        mov     dx,offset help_pt1
        mov     cx,help_pt1l
        cmp     printer_type,1
        je      info_9
        mov     dx,offset help_pt2
        mov     cx,help_pt2l
        cmp     printer_type,2
        je      info_9
        mov     dx,offset help_pt3
        mov     cx,help_pt3l
        cmp     printer_type,3
        je      info_9
        mov     dx,offset help_pt4
        mov     cx,help_pt4l
        cmp     printer_type,4
        je      info_9
        mov     dx,offset help_pt0
        mov     cx,help_pt0l
info_9: mov     bx,console_handle
        mov     ah,40h
        int     21h
        mov     dx,offset help_ptx
        mov     cx,help_ptxl
        mov     bx,console_handle
        mov     ah,40h
        int     21h
        ret
display_info endp


get_filename proc near          ;process name of the input file
                                ;DS:SI <- addr command line

        mov  si,offset command  ;ES:DI <- addr filespec buffer
        mov     di,offset input_name
        cld
        lodsb                   ;any command line present?
        or      al,al           ;return error status if not.
        jz      get_filename9
get_filename1:  lodsb           ;scan over leading blanks to file name
        cmp     al,20h          ;blank?
        je      get_filename1   ;yes, keep scanning.
        cmp     al,cr           ;C/R?
        jne     get_filename1a
get_filename1x:
        jmp     get_filename9
get_filename1a:
        cmp     al,'/'          ;or switch?
        jne     get_filename1b
get_filename1aL:
        lodsb
        cmp     al,cr
        je      get_filename1x
        cmp     al,' '
        jne     get_filename1aL
        jmp     get_filename1
get_filename1b:
        cmp     al,'"'          ;or quote mark (filename missing)
        jne     get_filename2   ;no, found filename
get_filename1bL:
        lodsb
        cmp     al,cr
        je      get_filename1x
        cmp     al,'"'
        jne     get_filename1bL
        jmp     get_filename1

get_filename2:
        push    si              ;save for title
        push    ax

get_filename4: stosb            ;found first char of name
                                ;move last char to output filename buffer
        lodsb                   ;check next char found
        cmp     al,cr           ;C/R yet?
        je      get_filename5   ;yes,exit with success code
        cmp     al,'"'          ;quote encountered?
        je      get_filename5
        cmp     al,20h          ;blank?
        jne     get_filename4   ;no, keep moving chars
get_filename5:
        pop     ax              ;get saved values (and restore stack)
        pop     si
        test    ttl_flag,-1     ;was a title specified?
        jnz     get_filename8   ;yes, exit.
        mov     di,offset heading1
        mov     bl,max_title+1
        mov     titlecount,bl
get_filename7: stosb
        lodsb
        dec     titlecount
        jz      get_filename8
        cmp     al,cr           ;test for end
        je      get_filename8
        cmp     al,'"'
        je      get_filename8
        cmp     al,20h
        jne     get_filename7
get_filename8:
        clc                     ;for success flag
        ret
get_filename9:                  ;exit with carry=1 for error flag
        stc
        ret
get_filename endp


get_title proc near             ;process title for listing
        mov     al,max_title+1
        mov     titlecount,al
        mov     si,offset command    ;DS:SI <- addr command line
        mov     di,offset heading1   ;ES:DI <- addr page heading buffer
        cld
        lodsb                   ;any command line present?
        or      al,al           ;no, exit
        jz      get_title3
get_title1:     lodsb           ;scan for leading <"> to find title.
        cmp     al,cr           ;C/R?
        je      get_title3      ;yes, title text missing.
        cmp     al,'"'          ;delimiter found?
        jne     get_title1      ;no, continue scanning
        mov     ttl_flag,-1     ;indicate title specified
get_title2:     lodsb           ;get next char of title
        cmp     al,'"'          ;terminate if second <"> char
        je      get_title3      ;or C/R found.
        cmp     al,cr
        je      get_title3
        stosb                   ;store char into page heading buffer
        dec     titlecount
        jnz     get_title2      ;and continue scan
get_title3:  ret
get_title endp


get_date proc near              ;get date/time, insert into title
        mov     ah,2Ch          ;time-of-day
        int     21h
        xor     ax,ax
        mov     al,ch
        aam                     ;convert to decimal chars
        add     ax,'00'
        mov     heading_hh,ah
        mov     heading_hh+1,al
        xor     ax,ax
        mov     al,cl
        aam
        add     ax,'00'
        mov     heading_mm,ah
        mov     heading_mm+1,al
        mov     ah,2Ah          ;get date
        int     21h
        xor     ax,ax           ;clear
        mov     al,dl           ;do day
        aam
        add     ax,'00'
        mov     heading_day,ah
        mov     heading_day+1,al
        xor     ax,ax           ;clear
        mov     al,dh           ;do month
        aam
        add     ax,'00'
        mov     heading_month,ah
        mov     heading_month+1,al
        mov     ax,cx           ;do year
        sub     ax,1900
        aam
        add     ax,'00'
        mov     heading_year,ah
        mov     heading_year+1,al
        ret
get_date endp



get_option proc near            ;Scan the input line and determine the
                                ;run-time options (parameters).
        mov     si,offset command+1  ;DS:SI=addr of command line
        cld
gopt00: lodsb                   ;look for "/"
gopt01: cmp     al,cr           ;C/R?
        jne     gopt03          ;not end, continue
gopt02: ret                     ;exit
gopt03: cmp     al,' '          ;blank?
        je      gopt00          ;yes, try next
        cmp     al,'"'          ;title?
        jne     gopt08          ;no, continue
gopt05: lodsb
        cmp     al,cr
        je      gopt02
        cmp     al,'"'
        je      gopt00
        jmp     gopt05
gopt08: cmp     al,'/'          ;is this and option?
        je      gopt10          ;yes, process option
gopt09: lodsb                   ;find next parm
        cmp     al,cr
        je      gopt02          ;exit   ?
        cmp     al,'/'
        je      gopt10
        cmp     al,' '          ;end of this parm?
        jne     gopt09          ;no, continue
        jmp     gopt00          ;yes

gopt10: lodsb                   ;found, get next char
        or      al,20h          ;fold to lower case

        cmp     al,'f'
        jne     gopt18
        lodsb
        cmp     al,'='
        jne     gopt01
        lodsb
        cmp     al,'1'
        jb      gopt01
        cmp     al,'5'
        ja      gopt01
        and     al,07h
        mov     flg_font,al
        jmp     gopt09
gopt18:
        cmp     al,'x'          ;x=translate
        jne     gopt20
        mov     xlate_switch,-1 ;set translate
        jmp     gopt09
gopt20: cmp     al,'s'          ;s=strip
        jne     gopt24
        mov     strip_switch,-1 ;set input-strip
        jmp     gopt09
gopt24: cmp     al,'t'          ;t=terminal (the console or screen)
        jne     gopt26
        mov     term_switch,-1 ;set print switch
        jmp     gopt09
gopt26: cmp     al,'i'          ;i=indent
        jne     gopt30
        mov     flg_indent,-1   ;set indent switch
        jmp     gopt09
gopt30: cmp     al,'8'
        jne     gopt32
        mov     flg_lpi,8       ;8 lpi
        jmp     gopt09
gopt32: cmp     al,'6'
        jne     gopt40
        mov     flg_lpi,6       ;6 lpi
        jmp     gopt09
gopt40: cmp     al,'n'          ;n=number (sequence numbering)
        jne     gopt50
        mov     num_switch,-1   ;set sequence numbering switch
        jmp     gopt09
gopt50: cmp     al,'c'          ;COPY
        jne     gopt60
        mov     flg_copy,-1
        jmp     gopt09
gopt60: cmp     al,'d'          ;Device spec
        jne     gopt70
        lodsb
        cmp     al,'='
        je      gopt62
gopt61: jmp     gopt01
gopt62: lodsb
        cmp     al,'1'
        jb      gopt61
        cmp     al,'4'
        ja      gopt61
        and     al,07h
        mov     printer_type,al
        jmp     gopt09
gopt70: cmp     al,'z'
        jne     gopt80
        mov     flg_no_eof,-1
        jmp     gopt09
gopt80: jmp     gopt09

get_option endp

set_option proc near            ;set run-time options
        cld
        mov     di,offset init_printer
        mov     init_printer_length,0


sopt10: cmp     printer_type,1  ;Epson
        jne     sopt20
        mov     al,012h
        stosb
        inc     init_printer_length
        cmp     flg_font,1      ;10cpi?
        je      sopt11          ;yes
        mov     al,0fh          ;everything else
        stosb
        inc     init_printer_length
sopt11: mov     al,01bh         ; set lines/inch vertical
        stosb
        mov     pagesize,60     ;assume 6 lpi
        mov     al,50
        cmp     flg_lpi,8
        jne     sopt14
        mov     pagesize,80     ;set 8 lpi
        mov     al,48
sopt14: stosb
        add     init_printer_length,2
        jmp     sopt90

sopt20: cmp     printer_type,2  ;Gemini Star 10x
        jne     sopt30
        mov     al,01bh         ; set font
        stosb
        mov     al,042h
        stosb
        mov     al,1            ;10cpi
        mov     bl,3
        cmp     flg_font,1
        je      sopt21
        mov     al,2            ;12cpi
        mov     bl,4
        cmp     flg_font,2
        je      sopt21
        mov     al,3            ;15,17cpi -- and everything else
        mov     bl,5
sopt21: stosb
        mov     al,01bh         ;set indent
        stosb
        mov     al,04dh
        stosb
        mov     al,0
        cmp     flg_indent,0
        je      sopt22
        mov     al,bl
sopt22: stosb
        mov     al,01bh         ; set lines/inch vertical
        stosb
        mov     pagesize,60     ;assume 6 lpi
        mov     al,50
        cmp     flg_lpi,8
        jne     sopt24
        mov     pagesize,80     ;set 8 lpi
        mov     al,48
sopt24: stosb
        add     init_printer_length,8
        jmp     sopt90

sopt30: cmp     printer_type,3  ;NEC p6/p7
        je      sopt31
        jmp     sopt40
sopt31: mov     al,012h         ;cancel condensed
        stosb
        inc     init_printer_length
        mov     bl,0
        cmp     flg_font,1      ;10cpi
        jne     sopt32
        mov     al,01bh
        stosb
        mov     al,05dh
        stosb
        add     init_printer_length,2
        mov     bl,3
        jmp     sopt36
sopt32: cmp     flg_font,2      ;12cpi
        jne     sopt33
        mov     al,01bh
        stosb
        mov     al,04dh
        stosb
        add     init_printer_length,2
        mov     bl,4
        jmp     sopt36
sopt33: cmp     flg_font,3      ;15cpi
        jne     sopt34
        mov     al,01bh
        stosb
        mov     al,067h
        stosb
        add     init_printer_length,2
        mov     bl,5
        jmp     sopt36
sopt34: cmp     flg_font,4      ;17cpi
        jne     sopt35
        mov     al,01bh
        stosb
        mov     al,05dh
        stosb
        mov     al,0fh
        stosb
        add     init_printer_length,3
        mov     bl,5
        jmp     sopt36
sopt35: cmp     flg_font,5      ;20cpi
        jne     sopt36
        mov     al,01bh
        stosb
        mov     al,04dh
        stosb
        mov     al,0fh
        stosb
        add     init_printer_length,3
        mov     bl,6
        jmp     sopt36
sopt36: mov     al,01bh         ;set indent
        stosb
        mov     al,06ch
        stosb
        mov     al,0
        cmp     flg_indent,0
        je      sopt37
        mov     al,bl
sopt37: stosb
        add     init_printer_length,3
        mov     al,01bh         ; set lines/inch vertical
        stosb
        mov     pagesize,60     ;assume 6 lpi
        mov     al,50
        cmp     flg_lpi,8
        jne     sopt39
        mov     pagesize,80     ;set 8 lpi
        mov     al,48
sopt39: stosb
        add     init_printer_length,2
        jmp     sopt90

sopt40: cmp     printer_type,4  ;IBM Proprinter
        jne     sopt50
        cmp     flg_font,1      ;10cpi
        jne     sopt42
        mov     al,012h
        stosb
        inc     init_printer_length
        jmp     sopt46
sopt42: cmp     flg_font,2      ;12cpi
        jne     sopt43
        mov     al,01bh
        stosb
        mov     al,03ah
        stosb
        add     init_printer_length,2
        jmp     sopt46
sopt43:                         ;17cpi and everything else
        mov     al,0fh
        stosb
        inc     init_printer_length
        jmp     sopt46
sopt46:
        mov     al,01bh         ; set lines/inch vertical
        stosb
        mov     pagesize,60     ;assume 6 lpi
        mov     al,50
        cmp     flg_lpi,8
        jne     sopt49
        mov     pagesize,80     ;set 8 lpi
        mov     al,48
sopt49: stosb
        add     init_printer_length,2
        jmp     sopt90
sopt50:
        jmp     sopt90

sopt90:
        ret
set_option endp


open_input proc near            ;open the input file
        mov     dx,offset input_name  ;DS:DX=addr filename
        mov     al,0            ;read-only
        mov     ah,3dh          ;function=3dh for open
        int     21h             ;handle return in ax
        mov     input_handle,ax ;save it for later
        ret                     ;CY is set if error
open_input endp


get_char proc near              ;get one char from input buffer
get_char0:
        mov     bx,input_ptr    ;is pntr at end of buffer?
        cmp     bx,blksize
        jne     get_char1       ;no
        call    read_block      ;yes, new block must be read
        mov     bx,0            ;init pntr
        mov     input_ptr,bx
        cmp     input_buffer_len,0  ;end?
        jne     get_char1       ;no, continue
        mov     al,eof
        ret
get_char1: mov  al,[input_buffer+bx]
        inc     bx              ;inc pntr
        mov     input_ptr,bx
        cmp     al,20h          ;is it a control code?
        jae     get_char6       ;no, continue.
        cmp     flg_no_eof,0
        je      get_char9       ;not skiping eof's
        cmp     al,eof
        je      get_char0
        ret
get_char6: cmp strip_switch,0   ;stripping?
        je      get_char7       ;no
        and     al,7fh          ;yes
        ret
get_char7: cmp  xlate_switch,0  ;translating?
        je      get_char9
        cmp     al,80h          ;special char?
        jae     get_char8       ;yes
        ret                     ;no
get_char8: mov  bx,0            ;yes, do xlate
        mov     bl,al
        mov     al,[Xtbl+bx]
        ret
get_char9:
        ret
get_char endp


put_char proc near              ;put one char into output buffer
        mov     bx,output_ptr
        mov     [output_buffer+bx],al  ;insert char in buffer
        inc     output_ptr      ;and update pntr/counter
        ret
put_char endp


read_block proc near            ;read block of data from input file
        mov     bx,input_handle
        mov     cx,blksize
        mov     dx,offset input_buffer
        mov     ah,3fh
        int     21h
        jnc     read_block1     ;if no error
        mov     ax,0            ;fake zero length if error
read_block1:
        mov     input_buffer_len,ax
        cmp     ax,blksize      ;was a full buffer read?
        je      read_block2     ;yes
        mov     bx,ax           ;no, store e-o-f mark
        mov     byte ptr [input_buffer+bx],eof
read_block2: mov input_ptr,0    ;init pntr to input buffer
        ret
read_block endp


write_maybe proc near           ;output line if buffer contains anything
        mov     ax,output_ptr   ;pntr is non-zero if data in buffer
        or      ax,ax
        jz      write_maybe1    ;nothing, exit
        call    write_line      ;something is there, output it.
write_maybe1: ret
write_maybe  endp


write_line      proc near       ;transmit contents of output buffer to
                                ;the standard list device.

        cmp     num_switch,0
        je      write_line5
        inc     linenumber
        mov     ax,linenumber
        mov     bx,offset output_number
        call    Convert
write_line5:
        mov     cx,output_ptr   ;CX contains length of string
        mov     dx,offset output_buffer ;DX:DX=buffer addr
        cmp     num_switch,0
        je      write_line7
        add     cx,6
        mov     dx,offset output_number
write_line7:
        mov     bx,output_handle;BX=handle for standard list device.
        mov     ah,40h          ;function 40h = write to device
        int     21h
        inc     linecount       ;for lines/page
        mov     output_ptr,0    ;reset buffer pntr
        ret
write_line endp


heading_maybe proc near         ;print heading if linecount justifies it
        cmp     flg_copy,0
        jne     heading_maybe2  ;skip ff if just on linecount
        mov     ax,linecount
        cmp     ax,pagesize
        jb      heading_maybe2  ;page not full yet.
        call    print_heading   ;FormFeed and print heading
heading_maybe2: ret
heading_maybe   endp


print_heading proc near         ;PRINT FormFeed, title and Page Number
        inc     pagecount       ;update page number
        mov     ax,pagecount    ;get it and convert to ascii
        mov     bx,offset heading2
        call    Convert
        mov     dx,offset heading_buffer ;now print the heading string
        mov     cx,heading_length
        cmp     flg_copy,0
        je      print_heading_3
        mov     cx,1
print_heading_3:
        mov     bx,output_handle
        mov     ah,40h
        int     21h
        test    term_switch,-1  ;console output?
        jne     print_heading_5
        mov     al,ff           ;printer, set formfeed after first one.
        mov     heading_buffer,al
print_heading_5:
        mov     linecount,heading_lines  ;init line count
        mov     column,0        ;and column counter
        ret
print_heading endp

Convert proc near               ;convert binary to ASCII
        push    dx
        push    si
        mov     cx,5
Conv1:  mov     byte ptr [bx],' '  ;clear buffer
        inc     bx
        loop    Conv1
        mov     si,10              ;to get digits
        or      ax,ax              ;force positive
        jns     conv5
        neg     ax
Conv5:  sub     dx,dx
        div     si                 ;divide by 10
        add     dx,'0'
        dec     bx
        mov     [bx],dl            ;insert digit into output
        or      ax,ax              ;if zero, done
        jnz     Conv5
        pop     si
        pop     dx
        ret
Convert endp

xprt    ends

        end main

