	load 'macros.dump'
	include 'driver.equ'
	include 'wp.equ'

;-----------------------------------------------
;
;   Imported addresses
;
;-----------------------------------------------

	IMPORT	D_AlertBox
	IMPORT	D_BeachBall
	IMPORT	W_CalcDocRect
	IMPORT	W_CalcPages
	IMPORT	W_CurDoc
	IMPORT	W_DeleteText
	IMPORT	W_EndLine
	IMPORT	W_EndOffset
	IMPORT	W_EndPar
	IMPORT	W_FindLine
	IMPORT	W_GetAddr
	IMPORT	W_GotoBeg
	IMPORT	W_GotoEnd
	IMPORT	W_InvSelect
	IMPORT	D_IsLetter
	IMPORT	W_MakeLines
	IMPORT	D_MemoryError
	IMPORT	W_PasteAscii
	IMPORT	W_PasteStr
	IMPORT	W_SelectOff
	IMPORT	W_SelectText
	IMPORT	D_SetCursor
	IMPORT	W_UpdateAfter
	IMPORT	W_UpdateDoc
	IMPORT	W_WordBounds
	IMPORT	W_Char
	IMPORT	W_def_replace
	IMPORT	W_def_search
	IMPORT	W_firstline
	IMPORT	W_firstoff
	IMPORT	W_firstpar
	import	W_foundonce
	IMPORT	W_ignoreValue
	IMPORT	W_LastP
	IMPORT	W_lastline
	IMPORT	W_lastoff
	IMPORT	W_lastpar
	IMPORT	W_oldslin
	IMPORT	Q_Rect
	IMPORT	W_Selected
	IMPORT	W_StartLine
	IMPORT	W_StartOffset
	IMPORT	W_StartPar
	IMPORT	D_State
	IMPORT	W_target
	IMPORT	D_ToLowerTable
	IMPORT	D_ToUpperTable
	
	IMPORT	W_visRect
	IMPORT	W_wholeValue

;-----------------------------------------------
;
;   Forward addresses and entries
;
;-----------------------------------------------

	ENTRY	W_GetTarget
	ENTRY	W_JustFind
	ENTRY	W_SameChar
****************************************************************
*															  	;
*				 The real word of Find/Replace					;
*______________________________________________________________*
*															 	;
*		CONTENTS:											 	;
*			  W_FindIt										  	;
*			  W_ReplaceIt									   		;
*			  W_ReplaceFind									 	;
*			  W_ReplaceAll									  	;
*			  W_StartOver									   		;
*															  	;
****************************************************************


********************************************************************
*	Includes...
*
* Monday, May 1, 1989 2:06:56 AM
********************************************************************
		


****************************************************************
*
*   W_FindIt -- Find and select the next (or previous) occurrence
*		of the target string.
*
****************************************************************
W_FindIt	PROC		EXPORT
			;Using	WPGlobals
			;Using	W_FRdlgData
			;Using	W_FRData

		begin

		jsl	  W_GetTarget	   ; Get the D_New W_target.

		jsl	  W_JustFind		; and find it, if possible
		jcc	  gotit
*--------------------------------------------------------------*
*	 If it isn't there, put up an alert, and redraw the WP	;
*	 window contents after the alert's gone				   ;
*--------------------------------------------------------------*
nomore	spaceword
		pushword #1			  ; just OK
		pushlong #tooBad
		jsl	  D_AlertBox
		pla

		pushlong W_CurDoc
		_SetPort

		pushlong W_CurDoc		  ; set the visRgn...
		_BeginUpdate
		pushlong W_CurDoc		  ; ...redraw...
		jsl	  W_UpdateDoc
		pushlong W_CurDoc		  ; ...and eat the D_Update event!
		_EndUpdate

		brl	  exit
*--------------------------------------------------------------*
*	   If it IS there, the hilite it and make it visible	  ;
*--------------------------------------------------------------*
gotit	pushlong W_CurDoc
		_SetPort

		jsl	  W_SelectOff

		spaceword
		pushword W_lastpar
		pushword W_lastoff
		jsl	  W_FindLine
		pullword W_lastline

		spaceword
		pushword W_firstpar
		pushword W_firstoff
		jsl	  W_FindLine
		pullword W_firstline

		pushword W_firstpar		; select the new text
		pushword W_firstline
		pushword W_firstoff
		pushword W_lastpar
		pushword W_lastline
		pushword W_lastoff
		pushlong #W_visRect
		jsl	  W_SelectText	  ; (in tools)

		jsl	  W_InvSelect

		inc	  W_foundonce

exit	pushword #arrowCursor
		jsl	  D_SetCursor

		return
*--------------------------------------------------------------*
*						 Useful Stuff						 ;
*--------------------------------------------------------------*
TooBad	str 'No more occurrences found.'

		ENDP

****************************************************************
*
*   W_GetTarget -- extract the target text from the search line
*		edit field, making allowances for options and display
*		characters.
*
****************************************************************
W_GetTarget	PROC		EXPORT
			;Using	W_FRData
			;Using	W_FRdlgData

		pushlong #W_def_search
		pushlong #W_target
		pushlong #60
		_BlockMove

		lda	  >W_ignoreValue	; if ignoring case, make sure that
		beq	  bye			 ;   letters are all caps

		short
		ldx #0
cloop	inx
		cpx W_target
		jgt bye

		lda W_target,x
		txy
		tax
		lda >D_ToUpperTable,x
		tyx
		sta W_target,x
		bra cloop

bye	long
		rtl

		ENDP

****************************************************************
*
*   W_JustFind -- just find the next occurrence of the target,
*		updating the paragraph and offset vars if successful.
*		Starts either at the insertion point or one character
*		past the start of the current selection.  Does not
*		select the found text.
*
*   This algorithm is really stupid, but the speedy algorithm
*		doesn't get you anything, since it would have to
*		look at every character twice: once to find the
*		text, and once to keep track of the beginning of the
*		found text.
*
*   Returns carry clear if and only if the target was found.
*
****************************************************************
W_JustFind	PROC		EXPORT
			;Using	W_FRData
			;Using	W_FRdlgData
			;Using	WPGlobals

		error	sorry
		local	W_Char:w,temp:l,D_State:w
		local	fpaddr:l,lpaddr:l
		local	fchar:w,lchar:w

		begin
		moveword #1,sorry

		moveword W_StartPar,W_firstpar
		moveword W_StartOffset,W_firstoff

		lda	  W_firstpar		; get the address of the paragraph
		ldx	  #0
		jsl	  W_GetAddr
		movelong ax,fpaddr

		ldy	  W_firstoff		; initialize the char variable
		lda	  [fpaddr],y
		and	  #$ff
		sta	  fchar
		sta	  W_Char

		lda	  W_Selected		; is there anything selected?
		beq	  noskip		  ; if not, don't skip a char!
*--------------------------------------------------------------*
*	 Look for a potential beginning for the target string	 ;
*--------------------------------------------------------------*
firstloop	jsr	  getnextf		; get the next start
noskip	lda	  W_target+1
		ldx	  W_Char
		jsl	  W_SameChar
		bcs	  notyet

		moveword W_firstpar,W_lastpar	   ; got it!
		moveword W_firstoff,W_lastoff
		movelong fpaddr,lpaddr
		moveword fchar,lchar
		moveword #1,D_State
		bra	  checkend

notyet	lda	  W_Char			; stop at the end of the document!
		bne	  firstloop
		brl	  exit
*--------------------------------------------------------------*
*		   Got a beginning -- now look for the rest		   ;
*--------------------------------------------------------------*
lastloop	inc	  D_State
		jsr	  getnextl		; loop through the target string
		ldx	  D_State
		lda	  W_target,x
		ldx	  W_Char
		jsl	  W_SameChar
		bcs	  notyet

checkend	lda	  W_target		  	; have I reached the end of the target?
		and	  #$ff					; (just one byte!!)
		cmp	  D_State
		beq	  foundit
		bra	  lastloop
*--------------------------------------------------------------*
*			 Found it!  Massage the limits and exit		   ;
*--------------------------------------------------------------*
foundit	jsr	  getnextl		; select to the next character
		lda	  W_Char			; (if there isn't one, forget it --
		beq	  exit			;  the last CR isn't really there.)

		lda	  >W_wholeValue
		beq	  really

		lda	  W_firstpar		; make sure the target starts and
		ldx	  W_firstoff		;  ends on word boundaries...
		jsl	  W_WordBounds
		cpx	  W_firstoff
		bne	  notyet

		cmpw	 lchar,#13	   	; ...or at a carriage return, since
		beq	  really		  	;  W_WordBounds acts differently there.

		lda	  W_lastpar
		ldx	  W_lastoff
		jsl	  W_WordBounds
		cpx	  W_lastoff
		bne	  notyet

really	stz	  sorry

exit	return
*--------------------------------------------------------------*
*				Get the next (first) character				;
*--------------------------------------------------------------*
getnextf	lda	  fchar
		beq	  fnomore
		cmp	  #13
		bne	  samefpar
		cmpw	 W_firstpar,W_LastP
		bne	  nextfpar

		stz	  fchar
fnomore	stz	  W_Char
		rts

nextfpar	inc	  W_firstpar
		lda	  W_firstpar
		ldx	  #0
		jsl	  W_GetAddr
		movelong ax,fpaddr

		moveword #W_TextHeader-1,W_firstoff

		jsl	  D_BeachBall

samefpar	shortm

		ldy	  W_firstoff
fnextloop	iny
		sty	  W_firstoff
		lda	  [fpaddr],y

		cmp	  #' '			; Is this a real character??
		bge	  gotfnext
		cmp	  #13
		beq	  gotfnext
		cmp	  #9
		beq	  gotfnext

		cmp	  #0
		beq	  fnextloop
		cmp	  #5
		bge	  fnextloop
		cmp	  #1
		bne	  faddone
		iny
faddone	iny
		bra	  fnextloop

gotfnext	sta	  W_Char
		sta	  fchar
		longm
		rts
*--------------------------------------------------------------*
*	 Get the next (last) character -- just like getnextf!!	;
*--------------------------------------------------------------*
getnextl	lda	  lchar
		beq	  lnomore
		cmp	  #13
		bne	  samelpar
		cmpw	 W_lastpar,W_LastP
		bne	  nextlpar

		stz	  lchar
lnomore	stz	  W_Char
		rts

nextlpar	inc	  W_lastpar
		lda	  W_lastpar
		ldx	  #0
		jsl	  W_GetAddr
		movelong ax,lpaddr

		moveword #W_TextHeader-1,W_lastoff

samelpar	shortm

		ldy	  W_lastoff
lnextloop	iny
		sty	  W_lastoff
		lda	  [lpaddr],y

		cmp	  #' '			; Is this a real character??
		bge	  gotlnext
		cmp	  #13
		beq	  gotlnext
		cmp	  #9
		beq	  gotlnext

		cmp	  #0
		beq	  lnextloop
		cmp	  #5
		bge	  lnextloop
		cmp	  #1
		bne	  laddone
		iny
laddone	iny
		bra	  lnextloop

gotlnext	sta	  W_Char
		sta	  lchar
		longm
		rts

		ENDP

****************************************************************
*
*   W_SameChar(a,x) -- carry clear if a and x are the 'same' char
*
*   Note:  Register A may change within this routine, but X will not.
*
****************************************************************
W_SameChar	PROC		EXPORT
			;Using	W_FRData
			;Using	W_FRdlgData

		php
		short

		sta	  temp2
		stx	  temp
		cmp	  temp
		beq	  yes

		cmp	  #0			  	; white space?
		bne	  notwhite
		cpx	  #$20				; space
		beq	  yes
		cpx	  #$d			 	; return
		beq	  yes
		cpx	  #9			  	; tab
		beq	  yes

notwhite	lda	  >W_ignoreValue	; ignore case?
		beq	  no

		lda temp
		longm
		and #$FF
		jsl D_IsLetter
		shortm
		bcs no

		lda >D_ToUpperTable,x
		cmp	  temp2				; then compare again!
		bne	  no

yes		plp
		clc
		rtl

no		plp
		sec
		rtl

temp		DS.B 2
temp2		DS.B 2

			longa	on
			longi	on

		ENDP

****************************************************************
*
*   W_ReplaceIt -- replace the W_Selected Q_Text with the replacement
*		Q_Text, and maintain the selection.
*
****************************************************************
W_ReplaceIt	PROC		EXPORT
			;Using	WpGlobals
			;Using	W_FRData
			;Using	W_FRdlgData

		local	spar:w,slin:w,soff:w
		local	epar:w,elin:w,eoff:w
		local	Q_Rect:r,select:w
		local	woff:w,W_oldslin:w,oops:w

		begin	+b

		pushlong W_CurDoc
		_SetPort

		lda	  W_StartPar		; save offset to start of first word
		ldx	  W_StartOffset
		jsl	  W_WordBounds
		stx	  woff
		moveword W_StartLine,W_oldslin

		spaceword
		spaceword
		spaceword
		spaceword
		pushlong #W_def_replace
		jsl	  W_PasteStr
		sta	  oops
		pullword select
		pullword eoff
		pullword elin
		pullword epar
		bcc	  okay

		jsl	  D_MemoryError

okay	moveword W_StartPar,spar
		moveword W_StartOffset,soff

		spaceword				; find the start line
		pushword spar
		pushword soff
		jsl	  W_FindLine
		pullword slin

		jsl	  W_SelectOff

		lda	  select
		beq	  nosel

		pushword spar
		pushword slin
		pushword soff
		pushword epar
		pushword elin
		pushword eoff
		pushlong #W_visRect
		jsl	  W_SelectText

nosel	spaceword				; update the text after the last line
		pushword spar			;  that could change (word might wrap
		pushword woff			;  up or down)
		jsl	  W_FindLine
		pla
		cmp	  W_oldslin
		bge	  D_Update
		sta	  W_oldslin

D_Update	pushword spar
		pushword W_oldslin
		jsl	  W_UpdateAfter

		return

		ENDP

****************************************************************
*
*   W_ReplaceFind -- replace, then find
*
****************************************************************
W_ReplaceFind	PROC		EXPORT
			;Using	WpGlobals
			;Using	W_FRData
			;Using	W_FRdlgData

		local	spar:w,slin:w,soff:w
		local	epar:w,elin:w,eoff:w
		local	Q_Rect:r,select:w
		local	woff:w,W_oldslin:w,oops:w

		begin	+b

		pushlong W_CurDoc
		_SetPort

		lda	  W_StartPar
		ldx	  W_StartOffset
		jsl	  W_WordBounds
		stx	  woff
		moveword W_StartLine,W_oldslin

		spaceword
		spaceword
		spaceword
		spaceword
		pushlong #W_def_replace
		jsl	  W_PasteStr
		sta	  oops
		pla
		pullword soff
		pullword slin
		pullword spar
		bcc	  okay

		jsl	  D_MemoryError

okay	jsl	  W_SelectOff

		spaceword				; update the text after the last line
		pushword W_StartPar		;  that could change (word might wrap
		pushword woff			;  up or down)
		jsl	  W_FindLine
		pla
		cmp	  W_oldslin
		bge	  D_Update
		sta	  W_oldslin

D_Update	pushword W_StartPar
		pushword W_oldslin
		jsl	  W_UpdateAfter

		moveword soff,W_StartOffset
		moveword slin,W_StartLine
		moveword spar,W_StartPar

		jsl	  W_FindIt

		return

		ENDP

****************************************************************
*
*   W_ReplaceAll
*
****************************************************************
W_ReplaceAll	PROC		EXPORT
			;Using	W_FRData
			;Using	W_FRdlgData
			;Using	WPglobals

		local	count:w,Q_Rect:r,oldpar:w,fastok:w,oops:w

		begin	+b

		jsl	  D_BeachBall

		jsl	  W_GetTarget	   		; get the new target.

		stz	  fastok		  	; See if the fast stuff is usable
		lda >W_wholeValue
		bne Norep
		short					;  (if neither string contatins a CR)

		ldx	  W_target
tloop	lda	  W_target,x
		cmp	  #13			 ; return?
		beq	  nope
		dex
		bne	  tloop

		lda	  >W_def_replace
		beq	  norep
		tax
rloop	lda	  >W_def_replace,x
		cmp	  #13			 ; return
		beq	  nope
		dex
		bne	  rloop

norep	inc	  fastok
nope	long

		pushlong W_CurDoc
		_SetPort

		jsl	  W_SelectOff

		stz	  count
		stz	  oldpar

raloop	jsl	  W_JustFind		; and find it, if possible
		jcs	  nomore

		jsl	  D_BeachBall

		lda	  fastok		  		; fast stuff?
		beq	  slowrep

		cmpw	 W_firstpar,oldpar 	; if same par, don't cut yet
		beq	  fastrep

		lda	  oldpar		  		; anything to cut?
		beq	  newold

		pushword oldpar
		jsl	  W_MakeLines
		jcs	  goterr

newold	moveword W_firstpar,oldpar

fastrep	pushword W_firstpar			; target and replacement are both 1 par
		pushword W_firstoff
		pushword W_lastoff
		jsl	  W_DeleteText

		pushlong #W_def_replace+1
		lda	  >W_def_replace
		and	  #$ff
		pha
		pushword W_firstpar
		pushword W_firstoff
		jsl	  W_PasteAscii
		sta	  oops

		moveword W_firstpar,W_StartPar
		lda	  >W_def_replace
		and	  #$ff
		clc
		adc	  W_firstoff
		sta	  W_StartOffset

		lda	  oops
		jne	  goterr

		inc	  count
		brl	  raloop

slowrep	spaceword					   	; target or replacement is more
		pushword W_lastpar				;  than one paragraph, so I
		pushword W_lastoff				;  can't use the fast stuff.
		jsl	  W_FindLine
		pullword W_lastline

		spaceword
		pushword W_firstpar
		pushword W_firstoff
		jsl	  W_FindLine
		pullword W_firstline

		moveword W_firstpar,W_StartPar
		moveword W_firstline,W_StartLine
		moveword W_firstoff,W_StartOffset
		moveword W_lastpar,W_EndPar
		moveword W_lastline,W_EndLine
		moveword W_lastoff,W_EndOffset

		spaceword
		spaceword
		spaceword
		spaceword
		pushlong #W_def_replace
		jsl	  W_PasteStr
		sta	  oops
		pla
		pullword W_StartOffset
		pullword W_StartLine
		pullword W_StartPar
		jcs	  goterr

		inc	  count
		brl	  raloop

nomore	lda	  oldpar		  	; remake the lines for the last
		beq	  noold		   		; paragraph (if necessary)

		pushword oldpar
		jsl	  W_MakeLines
		jcc	  noold

goterr	jsl	  D_MemoryError
		brl	  some

noold	lda	  count
		bne	  some

		spaceword
		pushword #1			  ; just OK
		pushlong #noneFound
		jsl	  D_AlertBox
		pla

		pushlong W_CurDoc		  ; draw to the WP window
		_SetPort

some	jsl	  W_CalcPages

		jsl	  W_GotoEnd

		pushlong !Q_Rect
		jsl	  W_CalcDocRect
		pushlong !Q_Rect
		_InvalRect

		pushlong W_CurDoc		  ; set the visRgn...
		_BeginUpdate
		pushlong W_CurDoc		  ; ...redraw...
		jsl	  W_UpdateDoc
		pushlong W_CurDoc		  ; ...and eat the update event!
		_EndUpdate

		pushword #arrowCursor
		jsl	  D_SetCursor

		return

noneFound	str 'No occurrences found.'

		ENDP

****************************************************************
*
*   W_StartOver
*
****************************************************************
W_StartOver	PROC		EXPORT
			;Using	WPglobals

		pushlong W_CurDoc
		_SetPort

		jsl	  W_SelectOff
		jsl	  W_GotoBeg

		rtl

		ENDP
		END