home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d6xx / d658 / view.lha / View / Source / ascii.s < prev    next >
Text File  |  1992-05-15  |  29KB  |  654 lines

  1.                     opt     l+,o+,ow-,inconce
  2.  
  3. *-- AutoRev header do NOT edit!
  4. *
  5. *   Program         :   ascii.s
  6. *   Copyright       :   © 1991 Jaba Development
  7. *   Author          :   Jan van den Baard
  8. *   Creation Date   :   16-Apr-91
  9. *   Current version :   1.1c
  10. *   Translator      :   Devpac 3 version 3.01
  11. *
  12. *   REVISION HISTORY
  13. *
  14. *   Date          Version         Comment
  15. *   ---------     -------         ------------------------------------------
  16. *   16-Apr-92     1.1c            Output code size = 1672 bytes
  17. *   16-Apr-92     1.1c            Fixed a few screw-ups.
  18. *   27-Mar-92     1.1b            Output code size = 1660 bytes.
  19. *   27-Mar-92     1.1b            Now assebles under Devpac 3
  20. *   12-Aug-91     1.1a            Output code size = 1664 bytes.
  21. *   12-Aug-91     1.1a            Added FindFrom routine.
  22. *   23-Apr-91     1.0c            Output code size = 1638 bytes.
  23. *   19-Apr-91     1.0b            Output code size = 1758 bytes.
  24. *   18-Apr-91     1.0a            Output code size = 1800 bytes.
  25. *   16-Apr-91     1.0             Output code size = 1808 bytes.
  26. *   16-Apr-91     1.0             Initial version! (Kickstart 1.2, 1.3 & 2.0 compatible!)
  27. *
  28. *-- REV_END --*
  29.  
  30.                     incdir  'sys:asm20/'
  31.                     include 'mymacros.i'
  32.                     include 'exec/types.i'
  33.                     include 'libraries/dos.i'
  34.                     include 'libraries/nofrag.i'
  35.                     include 'exec/exec_lib.i'
  36.                     include 'dos/dos_lib.i'
  37.                     include 'libraries/nofrag_lib.i'
  38.  
  39.                     include ':ascii.i'
  40.  
  41.                     xref        _DOSBase
  42.  
  43.                     xdef        _BOpen
  44.                     xdef        _BClose
  45.                     xdef        _BIoErr
  46.                     xdef        _BGetC
  47.                     xdef        _BPutC
  48.                     xdef        _BGetS
  49.                     xdef        _BPutS
  50.  
  51.                     xdef        _AllocAscii
  52.                     xdef        _FreeAscii
  53.                     xdef        _FindFrom
  54.                     xdef        _FirstOccurrence
  55.                     xdef        _NextOccurrence
  56.                     xdef        _PreviousOccurrence
  57.  
  58. PUBLIC              equ         MEMF_PUBLIC!MEMF_CLEAR
  59. LF                  equ         $0a
  60. TAB                 equ         $09
  61. ESC                 equ         $1b
  62. CSI                 equ         $9b
  63.  
  64. _SysBase            equ         $0004
  65.  
  66. _BOpen:             pushem.l d2-d4/a2-a3/a6
  67.  
  68.                     move.l  7*4(sp),a2              ; name to a2
  69.                     move.l  8*4(sp),d2              ; mode to d2
  70.  
  71.                     move.l  (_SysBase).w,a6
  72.                     move.l  #bio_SIZEOF,d0
  73.                     move.l  #PUBLIC,d1
  74.                     libcall AllocMem                ; allocate the structure
  75.                     move.l  d0,a3                   ; put it in a3
  76.                     tst.l   d0
  77.                     beq.s   NoFMem                  ; FAILED !?!?!
  78.                     move.l  d2,bio_FileMode(a3)     ; set file mode
  79.                     move.l  _DOSBase,a6
  80.                     move.l  a2,d1
  81.                     libcall Open                    ; try to open the file
  82.                     move.l  d0,bio_Handle(a3)       ; store the handle
  83.                     tst.l   d0
  84.                     beq.s   NoFile                  ; FAILED !?!?!
  85.                     lea.l   bio_Buffer(a3),a0
  86.                     move.l  a0,bio_Pointer(a3)      ; set byte pointer
  87.                     move.w  #ASE_OK,bio_Error(a3)   ; preset file error
  88.                     move.w  #0,bio_BytesLeft(a3)    ; no bytes in buffer
  89.                     move.l  #0,bio_BytesDone(a3)    ; no bytes IO'd
  90.                     move.l  a3,d0                   ; return the pointer
  91.                     bra.s   OAEnd
  92. NoFile:             move.l  (_SysBase).w,a6
  93.                     move.l  #bio_SIZEOF,d0
  94.                     move.l  a3,a1
  95.                     libcall FreeMem                 ; free the structure
  96. NoFMem:             cldat   d0                      ; return null (FAIL)
  97. OAEnd:              popem.l d2-d4/a2-a3/a6
  98.                     rts
  99.  
  100. *
  101. * You should ALWAYS check if this routine returns a ASE_WRITE error
  102. * because it writes the bytes still in the buffer to the file when
  103. * bufferd output has been performed with the file!
  104. *
  105. _BClose:            pushem.l d2-d4/a2/a6
  106.  
  107.                     move.l  6*4(sp),a2              ; file pointer to a2
  108.  
  109.                     cmp.l   #MODE_NEWFILE,bio_FileMode(a2)
  110.                     bne.s   IODone
  111.                     bsr     FlushBuffer             ; force bytes left to file
  112.                     blt.s   Err                     ; < 0 is error
  113.                     moveq   #ASE_OK,d2
  114. IODone:             move.l  _DOSBase,a6
  115.                     move.l  bio_Handle(a2),d1
  116.                     libcall Close                   ; close the file
  117.                     move.l  (_SysBase).w,a6
  118.                     move.l  #bio_SIZEOF,d0
  119.                     move.l  a2,a1
  120.                     libcall FreeMem                 ; deallocate the structure
  121.                     move.l  d2,d0
  122.                     popem.l d2-d4/a2/a6
  123.                     rts
  124. Err:                moveq   #ASE_WRITE,d2           ; write error !?!
  125.                     bra.s   IODone
  126.  
  127. _BIoErr:            move.l  4(sp),a0
  128.                     move.w  bio_Error(a0),d0        ; get last error from struct
  129.                     ext.l   d0                      ; correct long exstension
  130.                     rts
  131.  
  132. _BGetC:             pushem.l d2-d4/a2/a6
  133.  
  134.                     move.l  6*4(sp),a2              ; get file pointer in a2
  135.  
  136.                     cmp.l   #MODE_OLDFILE,bio_FileMode(a2)
  137.                     beq.s   RBOK                    ; file mode is ok
  138.                     move.w  #ASE_FILETYPE,bio_Error(a2)
  139.                     moveq   #ASE_EOF,d0             ; eof marks error
  140.                     bra.s   RBEnd
  141. RBOK:               tst.w   bio_BytesLeft(a2)       ; bytes left in buffer ?
  142.                     beq.s   FillBuff                ; no.. fill the buffer
  143. GByte:              move.l  bio_Pointer(a2),a0
  144.                     cldat   d0
  145.                     move.b  (a0)+,d0                ; get byte from buffer
  146.                     move.l  a0,bio_Pointer(a2)      ; update byte pointer
  147.                     dec.w   bio_BytesLeft(a2)
  148.                     bra.s   RBEnd
  149. FillBuff:           move.l  _DOSBase,a6
  150.                     move.l  bio_Handle(a2),d1       ; handle in d1
  151.                     move.l  a2,d2
  152.                     addq.w  #bio_Buffer,d2          ; buffer in d2
  153.                     move.l  #1024,d3
  154.                     libcall Read                    ; read bytes in buffer
  155.                     move.l  d0,d4                   ; # bytes read in d4
  156.                     blt.s   RErr
  157.                     beq.s   REof
  158.                     lea.l   bio_Buffer(a2),a0
  159.                     move.l  a0,bio_Pointer(a2)      ; reset byte pointer
  160.                     move.w  d4,bio_BytesLeft(a2)    ; reset bytes counter
  161.                     add.l   d4,bio_BytesDone(a2)    ; add # read to counter
  162.                     bra.s   GByte
  163. RErr:               move.w  #ASE_READ,bio_Error(a2) ; read error !?!
  164.                     moveq   #ASE_EOF,d0
  165.                     bra.s   RBEnd
  166. REof:               move.w  #ASE_EOF,bio_Error(a2)  ; end-of-file !?!
  167.                     moveq   #ASE_EOF,d0
  168. RBEnd:              popem.l d2-d4/a2/a6
  169.                     rts
  170.  
  171. _BPutC:             pushem.l d2-d5/a2/a6
  172.  
  173.                     move.l  7*4(sp),a2              ; get file pointer in a2
  174.  
  175.                     move.l  d0,d5                   ; byte to write in d5
  176.                     cmp.l   #MODE_NEWFILE,bio_FileMode(a2)
  177.                     beq.s   WBOK                    ; file mode is ok
  178.                     move.w  #ASE_FILETYPE,bio_Error(a2)
  179.                     moveq   #ASE_EOF,d0
  180.                     bra.s   WBEnd
  181. WBOK:               cmp.w   #1024,bio_BytesLeft(a2) ; room left in buffer ?
  182.                     beq.s   WriteBuff               ; no.. write the buffer
  183. PByte:              move.l  bio_Pointer(a2),a0
  184.                     move.b  d5,(a0)+                ; put byte in buffer
  185.                     move.l  a0,bio_Pointer(a2)      ; update byte pointer
  186.                     inc.w   bio_BytesLeft(a2)       ; increase byte count
  187.                     moveq   #ASE_OK,d0
  188.                     bra.s   WBEnd
  189. WriteBuff:          bsr.s   FlushBuffer             ; force bytes left to file
  190.                     blt.s   WErr
  191.                     lea.l   bio_Buffer(a2),a0
  192.                     move.l  a0,bio_Pointer(a2)      ; reset byte pointer
  193.                     move.w  #0,bio_BytesLeft(a2)    ; reset bytes counter
  194.                     add.l   d4,bio_BytesDone(a2)    ; add # read to counter
  195.                     bra.s   PByte
  196. WErr:               move.w  #ASE_WRITE,bio_Error(a2) ; write error !?!
  197.                     moveq   #ASE_EOF,d0
  198. WBEnd:              popem.l d2-d5/a2/a6
  199.                     rts
  200.  
  201. FlushBuffer:        move.l  _DOSBase,a6
  202.                     move.l  bio_Handle(a2),d1
  203.                     move.l  a2,d2
  204.                     addq.w  #bio_Buffer,d2
  205.                     cldat   d3
  206.                     move.w  bio_BytesLeft(a2),d3
  207.                     libcall Write                   ; write bytes from buffer
  208.                     move.l  d0,d4                   ; # bytes written in d4
  209.                     rts
  210.  
  211.                     xref    _NoFragBase
  212.  
  213. _AllocAscii:        pushem.l d2-d4/a2/a6
  214.  
  215.                     move.l  6*4(sp),d3              ; tabsize to d3
  216.                     move.l  7*4(sp),d4              ; maxchars to d4
  217.                     move.l  8*4(sp),d2              ; flags to d2
  218.  
  219.                     move.l  (_SysBase).w,a6
  220.                     moveq   #at_SIZEOF,d0
  221.                     move.l  #PUBLIC,d1
  222.                     libcall AllocMem                ; allocate the structure
  223.                     move.l  d0,a2                   ; put it in a2
  224.                     tst.l   d0
  225.                     beq.s   AANoMem                 ; FAILED !?!?!
  226.                     NEWLIST a2                      ; initialize list
  227.                     move.w  d2,at_Flags(a2)         ; set flags
  228.                     move.l  _NoFragBase,a6
  229.                     move.l  #4096,d0
  230.                     libcall GetMemoryChain          ; get memorychain struct
  231.                     move.l  d0,at_MemoryUsed(a2)    ; put it in asciitext struct
  232.                     tst.l   d0
  233.                     bne.s   AAChainOK
  234.                     move.l  (_SysBase).w,a6
  235.                     move.l  a2,a1
  236.                     moveq   #at_SIZEOF,d0
  237.                     libcall FreeMem
  238.                     cldat   d0
  239.                     bra.s   AANoMem
  240. AAChainOK:          cmp.w   #MINTAB,d3
  241.                     bcc.s   TOK
  242.                     move.w  #MINTAB,d3
  243.                     bra.s   CheckMax
  244. TOK:                cmp.w   #MAXTAB,d3
  245.                     bls.s   CheckMax
  246.                     move.w  #MAXTAB,d3
  247. CheckMax:           cmp.w   #5,d4
  248.                     bcc.s   MOK
  249.                     move.w  #5,d4
  250.                     bra.s   AAEnd
  251. MOK:                cmp.w   #MAXLINE,d4
  252.                     bls.s   AAEnd
  253.                     move.w  #MAXLINE,d4
  254. AAEnd:              move.w  d3,at_TabJump(a2)
  255.                     move.w  d4,at_MaxChars(a2)
  256.                     move.l  a2,d0
  257. AANoMem:            popem.l d2-d4/a2/a6
  258.                     rts
  259.  
  260. _FreeAscii:         pushem.l a2/a6
  261.  
  262.                     move.l  3*4(sp),a2              ; ascii pointer in a2
  263.  
  264.                     move.l  _NoFragBase,a6
  265.                     move.l  at_MemoryUsed(a2),a0
  266.                     moveq   #1,d0
  267.                     libcall FreeMemoryChain         ; free the text + chain
  268.                     move.l  (_SysBase).w,a6
  269.                     move.l  a2,a1
  270.                     moveq   #at_SIZEOF,d0
  271.                     libcall FreeMem                 ; free the structure
  272.                     popem.l a2/a6
  273.                     rts
  274.  
  275. _BGetS:             pushem.l d2-d7/a2-a6
  276.  
  277.                     move.l  12*4(sp),a2             ; file pointer to a2
  278.                     move.l  13*4(sp),a3             ; ascii pointer to a3
  279.  
  280.                     cldat   d4
  281.                     cldat   d5
  282.                     cldat   d6
  283.                     cldat   d7
  284.  
  285.                     move.w  at_TabJump(a3),d6
  286.                     move.w  d6,d7
  287.                     push.l  a2
  288.                     move.l  _NoFragBase,a6
  289.                     move.l  at_MemoryUsed(a3),d3
  290.                     move.l  d3,a0
  291.                     moveq   #ln_SIZEOF,d0
  292.                     moveq   #MEMF_PUBLIC,d1
  293.                     libcall AllocItem               ; allocate a line structure
  294.                     move.l  d0,a4                   ; put it in a4
  295.                     tst.l   d0
  296.                     beq     RLNoMem                 ; FAILED !?!?!
  297.                     lea.l   bio_Line(a2),a5         ; line buffer in a5
  298. LineLoop:           bsr     _BGetC                  ; read one byte
  299.                     move.l  d0,d2                   ; put it in d2
  300.                     blt     ReadDone                ; Eof ?
  301.                     cmp.b   #LF,d2                  ; is it a Line Feed ?
  302.                     bne.s   NotLF
  303.                     move.b  d2,(a5)+
  304. Max:                inc.w   d4
  305.                     move.w  d6,d7
  306.                     cldat   d0
  307.                     move.w  d4,d0
  308.                     add.w   d5,d0
  309.                     move.w  d0,ln_Size(a4)
  310.                     add.l   d0,at_NumBytes(a3)
  311.                     moveq   #MEMF_PUBLIC,d1
  312.                     move.l  d3,a0
  313.                     libcall AllocItem
  314.                     move.l  d0,ln_Text(a4)
  315.                     tst.l   d0
  316.                     bne.s   MemOK
  317.                     move.w  #ASE_NOMEM,bio_Error(a2)
  318.                     cldat   d0
  319.                     bra     RLEnd
  320. MemOK:              lea.l   bio_Line(a2),a0
  321.                     move.l  d0,a1
  322.                     move.w  ln_Size(a4),d0
  323.                     addq.w  #3,d0
  324.                     and.w   #-4,d0
  325.                     lsr.w   #2,d0
  326.                     dec.w   d0
  327. copy:               move.l  (a0)+,(a1)+
  328.                     dbra    d0,copy
  329.                     inc.w   at_NumLines(a3)
  330.                     move.l  a4,d0
  331.                     move.w  #ASE_OK,bio_Error(a2)
  332.                     bra     RLEnd
  333. NotLF:              move.w  at_MaxChars(a3),d0
  334.                     dec.w   d0
  335.                     cmp.w   d4,d0
  336.                     bne.s   NoSplit                 ; not at maximum
  337. Mx:                 or.w    #LNF_Split,ln_Flags(a4) ; set split flag
  338.                     inc.w   at_NumSplit(a3)
  339.                     dec.l   bio_Pointer(a2)
  340.                     dec.l   bio_BytesDone(a2)
  341.                     inc.w   bio_BytesLeft(a2)
  342.                     move.b  #LF,(a5)+               ; put a LF in the line
  343.                     bra     Max
  344. NoSplit:            cmp.b   #TAB,d2                 ; is it a TAB ?
  345.                     bne.s   NoTAB
  346.                     btst    #ATB_TabConvert,at_Flags(a3)
  347.                     bne.s   NoTAB                   ; no tab conversion
  348.                     cldat   d0
  349.                     move.w  d7,d0
  350.                     dec.w   d0
  351.                     dec.l   bio_BytesDone(a2)
  352. TabLoop:            cldat   d1
  353.                     move.w  at_MaxChars(a3),d1
  354.                     dec.w   d1
  355.                     cmp.w   d4,d1
  356.                     beq.s   Mx                      ; yes.. stop
  357.                     move.b  #' ',(a5)+              ; put blank in line
  358.                     inc.w   d4
  359.                     inc.l   bio_BytesDone(a2)       ; increase read counter
  360.                     dbra    d0,TabLoop
  361.                     move.w  d6,d7
  362.                     bra     LineLoop
  363. NoTAB:              btst    #ATB_SkipEsc,at_Flags(a3)
  364.                     bne.s   NoESC
  365.                     cmp.b   #ESC,d2                 ; is it a ESC ?
  366.                     beq.s   Esc                     ; yes!!
  367.                     cmp.b   #CSI,d2                 ; else is it a CSI ?
  368.                     bne.s   NoESC                   ; no!!
  369. Esc:                move.b  d2,(a5)+                ; put it in the line
  370.                     inc.w   d5
  371.                     sub.b   #' ',d2                 ; check for terminator
  372.                     cmp.b   #'?',d2
  373.                     bcs     NotYet
  374.                     cmp.b   #'Z',d2
  375.                     bls     LineLoop
  376.                     bra.s   GetB
  377. NotYet:             tst.b   d2
  378.                     beq     LineLoop
  379. GetB:               bsr     _BGetC                  ; read sequence byte
  380.                     move.l  d0,d2
  381.                     blt.s   ReadDone
  382.                     bra.s   Esc
  383. NoESC:              dec.w   d7
  384.                     bne.s   TabLeft
  385.                     move.w  d6,d7
  386. TabLeft:            inc.w   d4
  387.                     move.b  d2,(a5)+
  388.                     bra     LineLoop
  389. RLNoMem:            move.w  #ASE_NOMEM,bio_Error(a2)
  390.                     cldat   d0
  391.                     bra.s   RLEnd
  392. ReadDone:           cmp.w   #ASE_EOF,bio_Error(a2)
  393.                     beq.s   Feof
  394.                     cldat   d0
  395.                     bra.s   RLEnd
  396. Feof:               cldat   d0
  397.                     tst.w   d4
  398.                     bne     Max
  399.                     move.l  d3,a0
  400.                     move.l  a4,a1
  401.                     moveq   #ln_SIZEOF,d0
  402.                     libcall FreeItem
  403.                     cladr   a4
  404. LOK:                move.l  a4,d0
  405. RLEnd:              addq.w  #4,sp
  406.                     popem.l d2-d7/a2-a6
  407.                     rts
  408.  
  409. _BPutS:             pushem.l d2/a2-a3
  410.  
  411.                     move.l  4*4(sp),a2              ; asciifile in a2
  412.                     move.l  5*4(sp),a3              ; line in a3
  413.  
  414.                     cldat   d2
  415.                     move.w  ln_Size(a3),d2
  416.                     dec.w   d2
  417.                     btst    #LNB_Split,ln_Flags(a3) ; line split up ?
  418.                     beq.s   No                      ; no..
  419.                     dec.w   d2
  420. No:                 move.l  ln_Text(a3),a3
  421. NoSpt:              cldat   d0
  422.                     move.b  (a3)+,d0
  423.                     push.l  d0
  424.                     push.l  a2
  425.                     bsr     _BPutC                  ; write one char
  426.                     addq.w  #8,sp
  427.                     cmp.l   #ASE_EOF,d0
  428.                     beq.s   WRErr
  429.                     dbra    d2,NoSpt
  430.                     cldat   d0
  431.                     bra.s   WLEnd
  432. WRErr:              move.w  bio_Error(a2),d0
  433.                     ext.l   d0
  434. WLEnd:              popem.l d2/a2-a3
  435.                     rts
  436.  
  437. _FindFrom:          pushem.l d2-d5/a2-a6
  438.  
  439.                     move.l  10*4(sp),a2             ; get Ascii pointer in a2
  440.                     move.l  11*4(sp),a3             ; get string pointer in a3
  441.                     move.l  12*4(sp),a4             ; get search in a4
  442.                     move.l  13*4(sp),a5             ; get line in a5
  443.                     move.l  14*4(sp),d2             ; get case flag in d2
  444.  
  445.                     bra.s   Search                  ; start searching....
  446.  
  447. _FirstOccurrence:   pushem.l d2-d5/a2-a6
  448.  
  449.                     move.l  10*4(sp),a2             ; get Ascii pointer in a2
  450.                     move.l  11*4(sp),a3             ; get string pointer in a3
  451.                     move.l  12*4(sp),a4             ; get search in a4
  452.                     move.l  13*4(sp),d2             ; get case flag in d2
  453.  
  454.                     move.l  at_First(a2),a5         ; get first line in a5
  455. Search:             cldat   d5
  456.                     move.l  a3,a0
  457.                     bsr     StrLen
  458.                     move.l  d0,d4
  459. FFLoop:             tst.l   ln_Next(a5)
  460.                     beq.s   FFDone                  ; no more lines !
  461.                     move.l  ln_Text(a5),a6          ; Text pointer in a6
  462.                     cldat   d3
  463.                     move.w  ln_Size(a5),d3          ; line size in d3
  464.                     sub.w   d4,d3                   ; substract it from d3
  465.                     dec.w   d3
  466.                     tst.w   d3
  467.                     blt.s   FFNext                  ; when < 0 next line
  468. FFSLoop:            move.l  a6,a0
  469.                     move.l  a3,a1
  470.                     move.l  d4,d0
  471.                     tst.w   d2
  472.                     beq.s   FFNoCase
  473.                     bsr     StrnCmp                 ; compare (case dependant)
  474.                     bra.s   FFChecked
  475. FFNoCase:           bsr     StrniCmp                ; compare (case independant)
  476. FFChecked:          tst.l   d0
  477.                     beq.s   FFCLoop
  478.                     move.l  a5,sc_Line(a4)          ; set line in struct
  479.                     move.l  a3,sc_String(a4)        ; set string ptr in struct
  480.                     move.w  d4,sc_StringSize(a4)    ; set string size in struct
  481.                     move.w  d5,sc_TextOffset(a4)    ; set offset in struct
  482.                     move.l  a2,sc_Text(a4)          ; set Ascii pointer in struct
  483.                     move.l  a6,sc_Address(a4)       ; set address in struct
  484.                     moveq   #1,d0                   ; return TRUE
  485.                     bra.s   FFEnd
  486. FFCLoop:            inc.w   d5                      ; increase offset counter
  487.                     inc.w   a6                      ; increase text pointer
  488.                     dbra    d3,FFSLoop
  489. FFNext:             cldat   d5
  490.                     move.l  ln_Next(a5),a5          ; next line in a5
  491.                     bra.s   FFLoop
  492. FFDone:             moveq   #0,d0
  493. FFEnd:              popem.l d2-d5/a2-a6
  494.                     rts
  495.  
  496. _NextOccurrence:    pushem.l d2-d6/a2-a6
  497.  
  498.                     move.l  11*4(sp),a4             ; get Search pointer in a4
  499.                     move.l  12*4(sp),d2             ; get case flag in d2
  500.  
  501.                     push.l  sc_Address(a4)
  502.                     push.l  sc_Line(a4)
  503.                     push.w  sc_TextOffset(a4)
  504.                     move.l  sc_String(a4),a3        ; get string in a3
  505.                     cldat   d4
  506.                     move.w  sc_StringSize(a4),d4    ; get string size in d4
  507.                     move.l  sc_Line(a4),a5          ; get line in a5
  508.                     cldat   d5
  509.                     add.l   d4,sc_Address(a4)       ; add stringsize to address
  510.                     add.w   d4,sc_TextOffset(a4)    ; add stringsize to offset
  511. FNLoop:             tst.l   ln_Next(a5)
  512.                     beq.s   FNDone                  ; no more lines !
  513.                     move.l  sc_Address(a4),a6       ; next address in a6
  514.                     cldat   d3
  515.                     move.w  sc_TextOffset(a4),d5    ; text offset in d5
  516.                     move.w  ln_Size(a5),d3          ; line size in d3
  517.                     sub.w   d4,d3                   ; substract size from d3
  518.                     sub.w   d5,d3                   ; substract offset from d3
  519.                     dec.w   d3
  520.                     tst.w   d3
  521.                     blt.s   FNNext                  ; when < 0 next line
  522. FNSLoop:            move.l  a6,a0
  523.                     move.l  a3,a1
  524.                     move.l  d4,d0
  525.                     tst.w   d2
  526.                     beq.s   FNNoCase
  527.                     bsr     StrnCmp                 ; compare (case dependant)
  528.                     bra.s   FNChecked
  529. FNNoCase:           bsr     StrniCmp                ; compare (case independant)
  530. FNChecked:          tst.l   d0
  531.                     beq.s   FNCLoop
  532.                     move.l  a5,sc_Line(a4)          ; set line in struct
  533. FNNotSame:          move.w  d5,sc_TextOffset(a4)    ; set offset in struct
  534.                     move.l  a6,sc_Address(a4)       ; set next addres in struct
  535.                     moveq   #1,d0                   ; return TRUE
  536.                     add.l   #10,sp
  537.                     bra.s   FNEnd
  538. FNCLoop:            inc.w   d5                      ; increase offset counter
  539.                     inc.w   a6                      ; increase text pointer
  540.                     dbra    d3,FNSLoop
  541. FNNext:             cldat   d5
  542.                     move.w  #0,sc_TextOffset(a4)    ; clear offset
  543.                     move.l  ln_Next(a5),a5          ; next line in a5
  544.                     move.l  ln_Text(a5),sc_Address(a4) ; text address in struc
  545.                     bra.s   FNLoop
  546. FNDone:             pop.w   sc_TextOffset(a4)
  547.                     pop.l   sc_Line(a4)
  548.                     pop.l   sc_Address(a4)
  549.                     moveq   #0,d0
  550. FNEnd:              popem.l d2-d6/a2-a6
  551.                     rts
  552.  
  553. _PreviousOccurrence:
  554.                     pushem.l d2-d6/a2-a6
  555.  
  556.                     move.l  11*4(sp),a4             ; get Search pointer in a4
  557.                     move.l  12*4(sp),d2             ; get case flag in d2
  558.  
  559.                     push.l  sc_Address(a4)
  560.                     push.l  sc_Line(a4)
  561.                     push.w  sc_TextOffset(a4)
  562.                     move.l  sc_String(a4),a3        ; get string in a3
  563.                     cldat   d4
  564.                     move.w  sc_StringSize(a4),d4    ; get string size in d4
  565.                     move.l  sc_Line(a4),a5          ; get line in a5
  566.                     cldat   d5
  567.                     sub.l   d4,sc_Address(a4)
  568.                     sub.w   d4,sc_TextOffset(a4)
  569. FPLoop:             cmp.l   sc_Text(a4),a5
  570.                     beq   FPDone                    ; no more lines !
  571.                     move.l  sc_Address(a4),a6       ; address in a6
  572.                     cldat   d3
  573.                     move.w  sc_TextOffset(a4),d5    ; text offset in d5
  574.                     move.w  d5,d3                   ; and in d3
  575.                     tst.w   d3
  576.                     blt.s   FPPrev                  ; when < 0 previous line
  577. FPSLoop:            move.l  a6,a0
  578.                     move.l  a3,a1
  579.                     move.l  d4,d0
  580.                     tst.w   d2
  581.                     beq.s   FPNoCase
  582.                     bsr     StrnCmp                 ; compare (case dependant)
  583.                     bra.s   FPChecked
  584. FPNoCase:           bsr     StrniCmp                ; compare (case independant)
  585. FPChecked:          tst.l   d0
  586.                     beq.s   FPCLoop
  587.                     move.l  a5,sc_Line(a4)          ; set line in struct
  588. FPNotSame:          move.w  d5,sc_TextOffset(a4)    ; set offset in struct
  589.                     move.l  a6,sc_Address(a4)       ; set prev addres in struct
  590.                     add.l   #10,sp
  591.                     moveq   #1,d0                   ; return TRUE
  592.                     bra.s   FPEnd
  593. FPCLoop:            dec.w   d5                      ; decrease offset counter
  594.                     dec.w   a6                      ; decrease text pointer
  595.                     dbra    d3,FPSLoop
  596. FPPrev:             cldat   d5
  597.                     move.l  ln_Prev(a5),a5          ; previous line in a5
  598.                     move.w  ln_Size(a5),d0
  599.                     sub.w   d4,d0
  600.                     move.w  d0,sc_TextOffset(a4)
  601.                     move.l  ln_Text(a5),d0          ; text address in struc
  602.                     add.w   ln_Size(a5),d0
  603.                     sub.w   d4,d0
  604.                     move.l  d0,sc_Address(a4)
  605.                     bra     FPLoop
  606. FPDone:             pop.w   sc_TextOffset(a4)
  607.                     pop.l   sc_Line(a4)
  608.                     pop.l   sc_Address(a4)
  609.                     moveq   #0,d0
  610. FPEnd:              popem.l d2-d6/a2-a6
  611.                     rts
  612.  
  613. ToLower:            cmp.b   #'A',d0
  614.                     bmi.s   NotUpAlp                ; smaller than 'A'.. skip
  615.                     cmp.b   #'Z',d0
  616.                     bhi.s   NotUpAlp                ; bigger than 'Z'.. skip
  617.                     add.b   #' ',d0                 ; make lower case
  618. NotUpAlp:           rts
  619.  
  620. StrLen:             cldat   d0
  621. SLen:               tst.b   (a0)+
  622.                     beq.s   SLDone
  623.                     inc.l   d0
  624.                     bra.s   SLen
  625. SLDone:             rts
  626.  
  627. StrnCmp:            dec.w   d0
  628. Cmp:                move.b  (a0)+,d1
  629.                     cmp.b   (a1)+,d1                ; are they the same ?
  630.                     bne.s   Diff                    ; no..
  631.                     dbra    d0,Cmp                  ; loop until "x" chars done
  632. Same:               moveq   #1,d0                   ; they where the same
  633.                     rts
  634. Diff:               cldat   d0                      ; they were different
  635.                     rts
  636.  
  637. StrniCmp:           push.l  d2
  638.                     move.l  d0,d2
  639.                     dec.w   d2
  640. iCmp:               move.b  (a0)+,d0
  641.                     bsr     ToLower                 ; convert char to lower case
  642.                     move.b  d0,d1                   ; put it in d1
  643.                     move.b  (a1)+,d0
  644.                     bsr     ToLower                 ; convert char to lower case
  645.                     cmp.b   d0,d1
  646.                     bne.s   iDiff                   ; two chars are different
  647.                     dbra    d2,iCmp
  648. iSame:              pop.l   d2
  649.                     moveq   #1,d0                   ; strings where the same
  650.                     rts
  651. iDiff:              pop.l   d2
  652.                     cldat   d0                      ; strings where different
  653.                     rts
  654.