Metropoli BBS
VIEWER: rline.asm MODE: TEXT (ASCII)
; RLINE.ASM --- read line from text file (MS-DOS version)
; Copyright (c) 1989 Ziff Communications Co.
; PC Magazine * Ray Duncan
;
; Call with:    DS:DX = buffer address
;               CX    = buffer size
;               BX    = text file handle
;               
;               Buffer should be larger than any line that
;               will be encountered in the text file.
;
; Returns:      AX    = length of line including new-line
;                       delimiter character(s), or 0 if 
;                       end of file or no delimiter found.
;               DS:DX = text address
;
;               Other registers preserved.      

DGROUP  group   _DATA

_DATA   segment word public 'DATA'

nl      db      0dh,0ah                 ; MS-DOS logical new-line
nl_len  equ     $-nl

_DATA   ends

_TEXT   segment word public 'CODE'

        extrn   strndx:near             ; string search utility

        assume  cs:_TEXT

        public  rline
rline   proc    near

        push    bx                      ; save registers
        push    cx
        push    dx
        push    si
        push    di
        push    es

                                        ; read chunk from file...
        mov     ah,3fh                  ; Fxn 3FH = read
        int     21h                     ; transfer to MS-DOS
        jc      rline8                  ; jump if read error
        or      ax,ax                   ; end of file?
        jz      rline9                  ; yes, jump

        push    ax                      ; save actual data length
        push    bx                      ; save input file handle
        push    dx                      ; save buffer base address
        push    ds

        push    ds                      ; set up for delimiter search
        pop     es                      ; ES:DI = string to search
        push    dx
        pop     di
        mov     dx,ax                   ; DX = string length
        mov     si,DGROUP               ; DS:SI = delimiter address
        mov     ds,si
        mov     si,offset DGROUP:nl
        mov     bx,nl_len               ; BX = delimiter length 
        call    strndx                  ; search for delimiter

        pop     ds                      ; restore buffer base address
        pop     dx
        pop     bx                      ; restore input file handle
        pop     ax                      ; restore original read length
        jc      rline8                  ; jump if no delimiter found

        add     di,nl_len               ; calculate line length
        sub     di,dx
        push    di                      ; and save it

        sub     ax,di                   ; calculate read excess
        neg     ax
        cwd
        mov     cx,ax                   ; CX:DX = amount to back
        xchg    dx,cx                   ; up file pointer
        mov     ax,4201h                ; Function 42H = seek
        int     21h                     ; transfer to MS-DOS

        pop     ax                      ; get back line length
        jmp     rline9                  ; and return it to caller

rline8: xor     ax,ax                   ; end of file or other error,
                                        ; set line length = 0

rline9: pop     es                      ; restore registers
        pop     di
        pop     si
        pop     dx
        pop     cx
        pop     bx
        ret                             ; return line length

rline   endp

_TEXT   ends
        end
[ RETURN TO DIRECTORY ]