home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d570 / view.lha / View / ascii.s < prev    next >
Text File  |  1991-11-21  |  29KB  |  642 lines

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