                    opt     l+,o+,ow-,inconce

*-- AutoRev header do NOT edit!
*
*   Program         :   ascii.s
*   Copyright       :   © 1991 Jaba Development
*   Author          :   Jan van den Baard
*   Creation Date   :   16-Apr-91
*   Current version :   1.1c
*   Translator      :   Devpac 3 version 3.01
*
*   REVISION HISTORY
*
*   Date          Version         Comment
*   ---------     -------         ------------------------------------------
*   16-Apr-92     1.1c            Output code size = 1672 bytes
*   16-Apr-92     1.1c            Fixed a few screw-ups.
*   27-Mar-92     1.1b            Output code size = 1660 bytes.
*   27-Mar-92     1.1b            Now assebles under Devpac 3
*   12-Aug-91     1.1a            Output code size = 1664 bytes.
*   12-Aug-91     1.1a            Added FindFrom routine.
*   23-Apr-91     1.0c            Output code size = 1638 bytes.
*   19-Apr-91     1.0b            Output code size = 1758 bytes.
*   18-Apr-91     1.0a            Output code size = 1800 bytes.
*   16-Apr-91     1.0             Output code size = 1808 bytes.
*   16-Apr-91     1.0             Initial version! (Kickstart 1.2, 1.3 & 2.0 compatible!)
*
*-- REV_END --*

                    incdir  'sys:asm20/'
                    include 'mymacros.i'
                    include 'exec/types.i'
                    include 'libraries/dos.i'
                    include 'libraries/nofrag.i'
                    include 'exec/exec_lib.i'
                    include 'dos/dos_lib.i'
                    include 'libraries/nofrag_lib.i'

                    include ':ascii.i'

                    xref        _DOSBase

                    xdef        _BOpen
                    xdef        _BClose
                    xdef        _BIoErr
                    xdef        _BGetC
                    xdef        _BPutC
                    xdef        _BGetS
                    xdef        _BPutS

                    xdef        _AllocAscii
                    xdef        _FreeAscii
                    xdef        _FindFrom
                    xdef        _FirstOccurrence
                    xdef        _NextOccurrence
                    xdef        _PreviousOccurrence

PUBLIC              equ         MEMF_PUBLIC!MEMF_CLEAR
LF                  equ         $0a
TAB                 equ         $09
ESC                 equ         $1b
CSI                 equ         $9b

_SysBase            equ         $0004

_BOpen:             pushem.l d2-d4/a2-a3/a6

                    move.l  7*4(sp),a2              ; name to a2
                    move.l  8*4(sp),d2              ; mode to d2

                    move.l  (_SysBase).w,a6
                    move.l  #bio_SIZEOF,d0
                    move.l  #PUBLIC,d1
                    libcall AllocMem                ; allocate the structure
                    move.l  d0,a3                   ; put it in a3
                    tst.l   d0
                    beq.s   NoFMem                  ; FAILED !?!?!
                    move.l  d2,bio_FileMode(a3)     ; set file mode
                    move.l  _DOSBase,a6
                    move.l  a2,d1
                    libcall Open                    ; try to open the file
                    move.l  d0,bio_Handle(a3)       ; store the handle
                    tst.l   d0
                    beq.s   NoFile                  ; FAILED !?!?!
                    lea.l   bio_Buffer(a3),a0
                    move.l  a0,bio_Pointer(a3)      ; set byte pointer
                    move.w  #ASE_OK,bio_Error(a3)   ; preset file error
                    move.w  #0,bio_BytesLeft(a3)    ; no bytes in buffer
                    move.l  #0,bio_BytesDone(a3)    ; no bytes IO'd
                    move.l  a3,d0                   ; return the pointer
                    bra.s   OAEnd
NoFile:             move.l  (_SysBase).w,a6
                    move.l  #bio_SIZEOF,d0
                    move.l  a3,a1
                    libcall FreeMem                 ; free the structure
NoFMem:             cldat   d0                      ; return null (FAIL)
OAEnd:              popem.l d2-d4/a2-a3/a6
                    rts

*
* You should ALWAYS check if this routine returns a ASE_WRITE error
* because it writes the bytes still in the buffer to the file when
* bufferd output has been performed with the file!
*
_BClose:            pushem.l d2-d4/a2/a6

                    move.l  6*4(sp),a2              ; file pointer to a2

                    cmp.l   #MODE_NEWFILE,bio_FileMode(a2)
                    bne.s   IODone
                    bsr     FlushBuffer             ; force bytes left to file
                    blt.s   Err                     ; < 0 is error
                    moveq   #ASE_OK,d2
IODone:             move.l  _DOSBase,a6
                    move.l  bio_Handle(a2),d1
                    libcall Close                   ; close the file
                    move.l  (_SysBase).w,a6
                    move.l  #bio_SIZEOF,d0
                    move.l  a2,a1
                    libcall FreeMem                 ; deallocate the structure
                    move.l  d2,d0
                    popem.l d2-d4/a2/a6
                    rts
Err:                moveq   #ASE_WRITE,d2           ; write error !?!
                    bra.s   IODone

_BIoErr:            move.l  4(sp),a0
                    move.w  bio_Error(a0),d0        ; get last error from struct
                    ext.l   d0                      ; correct long exstension
                    rts

_BGetC:             pushem.l d2-d4/a2/a6

                    move.l  6*4(sp),a2              ; get file pointer in a2

                    cmp.l   #MODE_OLDFILE,bio_FileMode(a2)
                    beq.s   RBOK                    ; file mode is ok
                    move.w  #ASE_FILETYPE,bio_Error(a2)
                    moveq   #ASE_EOF,d0             ; eof marks error
                    bra.s   RBEnd
RBOK:               tst.w   bio_BytesLeft(a2)       ; bytes left in buffer ?
                    beq.s   FillBuff                ; no.. fill the buffer
GByte:              move.l  bio_Pointer(a2),a0
                    cldat   d0
                    move.b  (a0)+,d0                ; get byte from buffer
                    move.l  a0,bio_Pointer(a2)      ; update byte pointer
                    dec.w   bio_BytesLeft(a2)
                    bra.s   RBEnd
FillBuff:           move.l  _DOSBase,a6
                    move.l  bio_Handle(a2),d1       ; handle in d1
                    move.l  a2,d2
                    addq.w  #bio_Buffer,d2          ; buffer in d2
                    move.l  #1024,d3
                    libcall Read                    ; read bytes in buffer
                    move.l  d0,d4                   ; # bytes read in d4
                    blt.s   RErr
                    beq.s   REof
                    lea.l   bio_Buffer(a2),a0
                    move.l  a0,bio_Pointer(a2)      ; reset byte pointer
                    move.w  d4,bio_BytesLeft(a2)    ; reset bytes counter
                    add.l   d4,bio_BytesDone(a2)    ; add # read to counter
                    bra.s   GByte
RErr:               move.w  #ASE_READ,bio_Error(a2) ; read error !?!
                    moveq   #ASE_EOF,d0
                    bra.s   RBEnd
REof:               move.w  #ASE_EOF,bio_Error(a2)  ; end-of-file !?!
                    moveq   #ASE_EOF,d0
RBEnd:              popem.l d2-d4/a2/a6
                    rts

_BPutC:             pushem.l d2-d5/a2/a6

                    move.l  7*4(sp),a2              ; get file pointer in a2

                    move.l  d0,d5                   ; byte to write in d5
                    cmp.l   #MODE_NEWFILE,bio_FileMode(a2)
                    beq.s   WBOK                    ; file mode is ok
                    move.w  #ASE_FILETYPE,bio_Error(a2)
                    moveq   #ASE_EOF,d0
                    bra.s   WBEnd
WBOK:               cmp.w   #1024,bio_BytesLeft(a2) ; room left in buffer ?
                    beq.s   WriteBuff               ; no.. write the buffer
PByte:              move.l  bio_Pointer(a2),a0
                    move.b  d5,(a0)+                ; put byte in buffer
                    move.l  a0,bio_Pointer(a2)      ; update byte pointer
                    inc.w   bio_BytesLeft(a2)       ; increase byte count
                    moveq   #ASE_OK,d0
                    bra.s   WBEnd
WriteBuff:          bsr.s   FlushBuffer             ; force bytes left to file
                    blt.s   WErr
                    lea.l   bio_Buffer(a2),a0
                    move.l  a0,bio_Pointer(a2)      ; reset byte pointer
                    move.w  #0,bio_BytesLeft(a2)    ; reset bytes counter
                    add.l   d4,bio_BytesDone(a2)    ; add # read to counter
                    bra.s   PByte
WErr:               move.w  #ASE_WRITE,bio_Error(a2) ; write error !?!
                    moveq   #ASE_EOF,d0
WBEnd:              popem.l d2-d5/a2/a6
                    rts

FlushBuffer:        move.l  _DOSBase,a6
                    move.l  bio_Handle(a2),d1
                    move.l  a2,d2
                    addq.w  #bio_Buffer,d2
                    cldat   d3
                    move.w  bio_BytesLeft(a2),d3
                    libcall Write                   ; write bytes from buffer
                    move.l  d0,d4                   ; # bytes written in d4
                    rts

                    xref    _NoFragBase

_AllocAscii:        pushem.l d2-d4/a2/a6

                    move.l  6*4(sp),d3              ; tabsize to d3
                    move.l  7*4(sp),d4              ; maxchars to d4
                    move.l  8*4(sp),d2              ; flags to d2

                    move.l  (_SysBase).w,a6
                    moveq   #at_SIZEOF,d0
                    move.l  #PUBLIC,d1
                    libcall AllocMem                ; allocate the structure
                    move.l  d0,a2                   ; put it in a2
                    tst.l   d0
                    beq.s   AANoMem                 ; FAILED !?!?!
                    NEWLIST a2                      ; initialize list
                    move.w  d2,at_Flags(a2)         ; set flags
                    move.l  _NoFragBase,a6
                    move.l  #4096,d0
                    libcall GetMemoryChain          ; get memorychain struct
                    move.l  d0,at_MemoryUsed(a2)    ; put it in asciitext struct
                    tst.l   d0
                    bne.s   AAChainOK
                    move.l  (_SysBase).w,a6
                    move.l  a2,a1
                    moveq   #at_SIZEOF,d0
                    libcall FreeMem
                    cldat   d0
                    bra.s   AANoMem
AAChainOK:          cmp.w   #MINTAB,d3
                    bcc.s   TOK
                    move.w  #MINTAB,d3
                    bra.s   CheckMax
TOK:                cmp.w   #MAXTAB,d3
                    bls.s   CheckMax
                    move.w  #MAXTAB,d3
CheckMax:           cmp.w   #5,d4
                    bcc.s   MOK
                    move.w  #5,d4
                    bra.s   AAEnd
MOK:                cmp.w   #MAXLINE,d4
                    bls.s   AAEnd
                    move.w  #MAXLINE,d4
AAEnd:              move.w  d3,at_TabJump(a2)
                    move.w  d4,at_MaxChars(a2)
                    move.l  a2,d0
AANoMem:            popem.l d2-d4/a2/a6
                    rts

_FreeAscii:         pushem.l a2/a6

                    move.l  3*4(sp),a2              ; ascii pointer in a2

                    move.l  _NoFragBase,a6
                    move.l  at_MemoryUsed(a2),a0
                    moveq   #1,d0
                    libcall FreeMemoryChain         ; free the text + chain
                    move.l  (_SysBase).w,a6
                    move.l  a2,a1
                    moveq   #at_SIZEOF,d0
                    libcall FreeMem                 ; free the structure
                    popem.l a2/a6
                    rts

_BGetS:             pushem.l d2-d7/a2-a6

                    move.l  12*4(sp),a2             ; file pointer to a2
                    move.l  13*4(sp),a3             ; ascii pointer to a3

                    cldat   d4
                    cldat   d5
                    cldat   d6
                    cldat   d7

                    move.w  at_TabJump(a3),d6
                    move.w  d6,d7
                    push.l  a2
                    move.l  _NoFragBase,a6
                    move.l  at_MemoryUsed(a3),d3
                    move.l  d3,a0
                    moveq   #ln_SIZEOF,d0
                    moveq   #MEMF_PUBLIC,d1
                    libcall AllocItem               ; allocate a line structure
                    move.l  d0,a4                   ; put it in a4
                    tst.l   d0
                    beq     RLNoMem                 ; FAILED !?!?!
                    lea.l   bio_Line(a2),a5         ; line buffer in a5
LineLoop:           bsr     _BGetC                  ; read one byte
                    move.l  d0,d2                   ; put it in d2
                    blt     ReadDone                ; Eof ?
                    cmp.b   #LF,d2                  ; is it a Line Feed ?
                    bne.s   NotLF
                    move.b  d2,(a5)+
Max:                inc.w   d4
                    move.w  d6,d7
                    cldat   d0
                    move.w  d4,d0
                    add.w   d5,d0
                    move.w  d0,ln_Size(a4)
                    add.l   d0,at_NumBytes(a3)
                    moveq   #MEMF_PUBLIC,d1
                    move.l  d3,a0
                    libcall AllocItem
                    move.l  d0,ln_Text(a4)
                    tst.l   d0
                    bne.s   MemOK
                    move.w  #ASE_NOMEM,bio_Error(a2)
                    cldat   d0
                    bra     RLEnd
MemOK:              lea.l   bio_Line(a2),a0
                    move.l  d0,a1
                    move.w  ln_Size(a4),d0
                    addq.w  #3,d0
                    and.w   #-4,d0
                    lsr.w   #2,d0
                    dec.w   d0
copy:               move.l  (a0)+,(a1)+
                    dbra    d0,copy
                    inc.w   at_NumLines(a3)
                    move.l  a4,d0
                    move.w  #ASE_OK,bio_Error(a2)
                    bra     RLEnd
NotLF:              move.w  at_MaxChars(a3),d0
                    dec.w   d0
                    cmp.w   d4,d0
                    bne.s   NoSplit                 ; not at maximum
Mx:                 or.w    #LNF_Split,ln_Flags(a4) ; set split flag
                    inc.w   at_NumSplit(a3)
                    dec.l   bio_Pointer(a2)
                    dec.l   bio_BytesDone(a2)
                    inc.w   bio_BytesLeft(a2)
                    move.b  #LF,(a5)+               ; put a LF in the line
                    bra     Max
NoSplit:            cmp.b   #TAB,d2                 ; is it a TAB ?
                    bne.s   NoTAB
                    btst    #ATB_TabConvert,at_Flags(a3)
                    bne.s   NoTAB                   ; no tab conversion
                    cldat   d0
                    move.w  d7,d0
                    dec.w   d0
                    dec.l   bio_BytesDone(a2)
TabLoop:            cldat   d1
                    move.w  at_MaxChars(a3),d1
                    dec.w   d1
                    cmp.w   d4,d1
                    beq.s   Mx                      ; yes.. stop
                    move.b  #' ',(a5)+              ; put blank in line
                    inc.w   d4
                    inc.l   bio_BytesDone(a2)       ; increase read counter
                    dbra    d0,TabLoop
                    move.w  d6,d7
                    bra     LineLoop
NoTAB:              btst    #ATB_SkipEsc,at_Flags(a3)
                    bne.s   NoESC
                    cmp.b   #ESC,d2                 ; is it a ESC ?
                    beq.s   Esc                     ; yes!!
                    cmp.b   #CSI,d2                 ; else is it a CSI ?
                    bne.s   NoESC                   ; no!!
Esc:                move.b  d2,(a5)+                ; put it in the line
                    inc.w   d5
                    sub.b   #' ',d2                 ; check for terminator
                    cmp.b   #'?',d2
                    bcs     NotYet
                    cmp.b   #'Z',d2
                    bls     LineLoop
                    bra.s   GetB
NotYet:             tst.b   d2
                    beq     LineLoop
GetB:               bsr     _BGetC                  ; read sequence byte
                    move.l  d0,d2
                    blt.s   ReadDone
                    bra.s   Esc
NoESC:              dec.w   d7
                    bne.s   TabLeft
                    move.w  d6,d7
TabLeft:            inc.w   d4
                    move.b  d2,(a5)+
                    bra     LineLoop
RLNoMem:            move.w  #ASE_NOMEM,bio_Error(a2)
                    cldat   d0
                    bra.s   RLEnd
ReadDone:           cmp.w   #ASE_EOF,bio_Error(a2)
                    beq.s   Feof
                    cldat   d0
                    bra.s   RLEnd
Feof:               cldat   d0
                    tst.w   d4
                    bne     Max
                    move.l  d3,a0
                    move.l  a4,a1
                    moveq   #ln_SIZEOF,d0
                    libcall FreeItem
                    cladr   a4
LOK:                move.l  a4,d0
RLEnd:              addq.w  #4,sp
                    popem.l d2-d7/a2-a6
                    rts

_BPutS:             pushem.l d2/a2-a3

                    move.l  4*4(sp),a2              ; asciifile in a2
                    move.l  5*4(sp),a3              ; line in a3

                    cldat   d2
                    move.w  ln_Size(a3),d2
                    dec.w   d2
                    btst    #LNB_Split,ln_Flags(a3) ; line split up ?
                    beq.s   No                      ; no..
                    dec.w   d2
No:                 move.l  ln_Text(a3),a3
NoSpt:              cldat   d0
                    move.b  (a3)+,d0
                    push.l  d0
                    push.l  a2
                    bsr     _BPutC                  ; write one char
                    addq.w  #8,sp
                    cmp.l   #ASE_EOF,d0
                    beq.s   WRErr
                    dbra    d2,NoSpt
                    cldat   d0
                    bra.s   WLEnd
WRErr:              move.w  bio_Error(a2),d0
                    ext.l   d0
WLEnd:              popem.l d2/a2-a3
                    rts

_FindFrom:          pushem.l d2-d5/a2-a6

                    move.l  10*4(sp),a2             ; get Ascii pointer in a2
                    move.l  11*4(sp),a3             ; get string pointer in a3
                    move.l  12*4(sp),a4             ; get search in a4
                    move.l  13*4(sp),a5             ; get line in a5
                    move.l  14*4(sp),d2             ; get case flag in d2

                    bra.s   Search                  ; start searching....

_FirstOccurrence:   pushem.l d2-d5/a2-a6

                    move.l  10*4(sp),a2             ; get Ascii pointer in a2
                    move.l  11*4(sp),a3             ; get string pointer in a3
                    move.l  12*4(sp),a4             ; get search in a4
                    move.l  13*4(sp),d2             ; get case flag in d2

                    move.l  at_First(a2),a5         ; get first line in a5
Search:             cldat   d5
                    move.l  a3,a0
                    bsr     StrLen
                    move.l  d0,d4
FFLoop:             tst.l   ln_Next(a5)
                    beq.s   FFDone                  ; no more lines !
                    move.l  ln_Text(a5),a6          ; Text pointer in a6
                    cldat   d3
                    move.w  ln_Size(a5),d3          ; line size in d3
                    sub.w   d4,d3                   ; substract it from d3
                    dec.w   d3
                    tst.w   d3
                    blt.s   FFNext                  ; when < 0 next line
FFSLoop:            move.l  a6,a0
                    move.l  a3,a1
                    move.l  d4,d0
                    tst.w   d2
                    beq.s   FFNoCase
                    bsr     StrnCmp                 ; compare (case dependant)
                    bra.s   FFChecked
FFNoCase:           bsr     StrniCmp                ; compare (case independant)
FFChecked:          tst.l   d0
                    beq.s   FFCLoop
                    move.l  a5,sc_Line(a4)          ; set line in struct
                    move.l  a3,sc_String(a4)        ; set string ptr in struct
                    move.w  d4,sc_StringSize(a4)    ; set string size in struct
                    move.w  d5,sc_TextOffset(a4)    ; set offset in struct
                    move.l  a2,sc_Text(a4)          ; set Ascii pointer in struct
                    move.l  a6,sc_Address(a4)       ; set address in struct
                    moveq   #1,d0                   ; return TRUE
                    bra.s   FFEnd
FFCLoop:            inc.w   d5                      ; increase offset counter
                    inc.w   a6                      ; increase text pointer
                    dbra    d3,FFSLoop
FFNext:             cldat   d5
                    move.l  ln_Next(a5),a5          ; next line in a5
                    bra.s   FFLoop
FFDone:             moveq   #0,d0
FFEnd:              popem.l d2-d5/a2-a6
                    rts

_NextOccurrence:    pushem.l d2-d6/a2-a6

                    move.l  11*4(sp),a4             ; get Search pointer in a4
                    move.l  12*4(sp),d2             ; get case flag in d2

                    push.l  sc_Address(a4)
                    push.l  sc_Line(a4)
                    push.w  sc_TextOffset(a4)
                    move.l  sc_String(a4),a3        ; get string in a3
                    cldat   d4
                    move.w  sc_StringSize(a4),d4    ; get string size in d4
                    move.l  sc_Line(a4),a5          ; get line in a5
                    cldat   d5
                    add.l   d4,sc_Address(a4)       ; add stringsize to address
                    add.w   d4,sc_TextOffset(a4)    ; add stringsize to offset
FNLoop:             tst.l   ln_Next(a5)
                    beq.s   FNDone                  ; no more lines !
                    move.l  sc_Address(a4),a6       ; next address in a6
                    cldat   d3
                    move.w  sc_TextOffset(a4),d5    ; text offset in d5
                    move.w  ln_Size(a5),d3          ; line size in d3
                    sub.w   d4,d3                   ; substract size from d3
                    sub.w   d5,d3                   ; substract offset from d3
                    dec.w   d3
                    tst.w   d3
                    blt.s   FNNext                  ; when < 0 next line
FNSLoop:            move.l  a6,a0
                    move.l  a3,a1
                    move.l  d4,d0
                    tst.w   d2
                    beq.s   FNNoCase
                    bsr     StrnCmp                 ; compare (case dependant)
                    bra.s   FNChecked
FNNoCase:           bsr     StrniCmp                ; compare (case independant)
FNChecked:          tst.l   d0
                    beq.s   FNCLoop
                    move.l  a5,sc_Line(a4)          ; set line in struct
FNNotSame:          move.w  d5,sc_TextOffset(a4)    ; set offset in struct
                    move.l  a6,sc_Address(a4)       ; set next addres in struct
                    moveq   #1,d0                   ; return TRUE
                    add.l   #10,sp
                    bra.s   FNEnd
FNCLoop:            inc.w   d5                      ; increase offset counter
                    inc.w   a6                      ; increase text pointer
                    dbra    d3,FNSLoop
FNNext:             cldat   d5
                    move.w  #0,sc_TextOffset(a4)    ; clear offset
                    move.l  ln_Next(a5),a5          ; next line in a5
                    move.l  ln_Text(a5),sc_Address(a4) ; text address in struc
                    bra.s   FNLoop
FNDone:             pop.w   sc_TextOffset(a4)
                    pop.l   sc_Line(a4)
                    pop.l   sc_Address(a4)
                    moveq   #0,d0
FNEnd:              popem.l d2-d6/a2-a6
                    rts

_PreviousOccurrence:
                    pushem.l d2-d6/a2-a6

                    move.l  11*4(sp),a4             ; get Search pointer in a4
                    move.l  12*4(sp),d2             ; get case flag in d2

                    push.l  sc_Address(a4)
                    push.l  sc_Line(a4)
                    push.w  sc_TextOffset(a4)
                    move.l  sc_String(a4),a3        ; get string in a3
                    cldat   d4
                    move.w  sc_StringSize(a4),d4    ; get string size in d4
                    move.l  sc_Line(a4),a5          ; get line in a5
                    cldat   d5
                    sub.l   d4,sc_Address(a4)
                    sub.w   d4,sc_TextOffset(a4)
FPLoop:             cmp.l   sc_Text(a4),a5
                    beq   FPDone                    ; no more lines !
                    move.l  sc_Address(a4),a6       ; address in a6
                    cldat   d3
                    move.w  sc_TextOffset(a4),d5    ; text offset in d5
                    move.w  d5,d3                   ; and in d3
                    tst.w   d3
                    blt.s   FPPrev                  ; when < 0 previous line
FPSLoop:            move.l  a6,a0
                    move.l  a3,a1
                    move.l  d4,d0
                    tst.w   d2
                    beq.s   FPNoCase
                    bsr     StrnCmp                 ; compare (case dependant)
                    bra.s   FPChecked
FPNoCase:           bsr     StrniCmp                ; compare (case independant)
FPChecked:          tst.l   d0
                    beq.s   FPCLoop
                    move.l  a5,sc_Line(a4)          ; set line in struct
FPNotSame:          move.w  d5,sc_TextOffset(a4)    ; set offset in struct
                    move.l  a6,sc_Address(a4)       ; set prev addres in struct
                    add.l   #10,sp
                    moveq   #1,d0                   ; return TRUE
                    bra.s   FPEnd
FPCLoop:            dec.w   d5                      ; decrease offset counter
                    dec.w   a6                      ; decrease text pointer
                    dbra    d3,FPSLoop
FPPrev:             cldat   d5
                    move.l  ln_Prev(a5),a5          ; previous line in a5
                    move.w  ln_Size(a5),d0
                    sub.w   d4,d0
                    move.w  d0,sc_TextOffset(a4)
                    move.l  ln_Text(a5),d0          ; text address in struc
                    add.w   ln_Size(a5),d0
                    sub.w   d4,d0
                    move.l  d0,sc_Address(a4)
                    bra     FPLoop
FPDone:             pop.w   sc_TextOffset(a4)
                    pop.l   sc_Line(a4)
                    pop.l   sc_Address(a4)
                    moveq   #0,d0
FPEnd:              popem.l d2-d6/a2-a6
                    rts

ToLower:            cmp.b   #'A',d0
                    bmi.s   NotUpAlp                ; smaller than 'A'.. skip
                    cmp.b   #'Z',d0
                    bhi.s   NotUpAlp                ; bigger than 'Z'.. skip
                    add.b   #' ',d0                 ; make lower case
NotUpAlp:           rts

StrLen:             cldat   d0
SLen:               tst.b   (a0)+
                    beq.s   SLDone
                    inc.l   d0
                    bra.s   SLen
SLDone:             rts

StrnCmp:            dec.w   d0
Cmp:                move.b  (a0)+,d1
                    cmp.b   (a1)+,d1                ; are they the same ?
                    bne.s   Diff                    ; no..
                    dbra    d0,Cmp                  ; loop until "x" chars done
Same:               moveq   #1,d0                   ; they where the same
                    rts
Diff:               cldat   d0                      ; they were different
                    rts

StrniCmp:           push.l  d2
                    move.l  d0,d2
                    dec.w   d2
iCmp:               move.b  (a0)+,d0
                    bsr     ToLower                 ; convert char to lower case
                    move.b  d0,d1                   ; put it in d1
                    move.b  (a1)+,d0
                    bsr     ToLower                 ; convert char to lower case
                    cmp.b   d0,d1
                    bne.s   iDiff                   ; two chars are different
                    dbra    d2,iCmp
iSame:              pop.l   d2
                    moveq   #1,d0                   ; strings where the same
                    rts
iDiff:              pop.l   d2
                    cldat   d0                      ; strings where different
                    rts
