PUBLIC  ISearch, RSearch

EXTRN	CCenter:Near, FModeline:Near, FScreen:Near, .Msg:Near, .CLRMsg:Near
EXTRN	.CAPS:Near, .InCH:Near, .Screen:Near, Sound:Near, $Repeat:word
EXTRN	Macrodefinition:Byte, MacroInvocation:Byte, MACArg:Word, .Error0:Near
EXTRN	MainScreenDraw:Near, Maincommand:NEAR, FParse0:NEAR, $Repeat:Word
;---------------------------------------------------------------------------

	Page ,132
NAME FSearch

TITLE Search Command

IF2
	%OUT *Pass 2*
ENDIF

Program SEGMENT PARA	PUBLIC  'code'
	ASSUME  CS:Program, DS:Program, ES:Program, SS:Program

INCLUDE FDEF.DEF

$Fail		db	'FAILING '
$Header	 db	'I-SEARCH: '
$SString	db	10 dup ('SEARCH')
$Failed	 db	0
$LastLength	db	0

;----------------------------------------------------------------------
ISearch PROC	NEAR

	mov	BP, DS:BCB.FCursor
	xor	DX, DX
	mov	AX, ScreenSegment
	mov	ES, AX
	mov	CS:$Header, 'I'
	call	.CLRMsg
	mov	SI, Offset $Header
	mov	CX, 10
	call	.Msg

ISearchLoop:
	jmp	GetString
GSR:	cmp	CS:$Failed, 0
	jne	ISFail
	mov	CS:$LastLength, 0 ; chance for ^S over
ISearch1:
	mov	CS:$Header, 'I'
	mov	SI, DS:BCB.FCursor
	sub	SI, DX
	call	.Find
	or	AH, AH
	jnz	ISFail0


ISOK:	add	SI, DX
	mov	DS:BCB.FCursor, SI
	call	.SScreen
	call	.CLRMsg
	mov	SI, Offset $Header
	mov	CX, 10
	add	CX, DX
	call	.Msg
	mov	CS:$Failed, 0
	jmp	ISearchLoop

ISFail0:dec	DS:BCB.FCursor
ISFail: mov	CS:$Failed, 0FFh
	push	DX
	call	Sound
	call	.CancelMacro
	call	.CLRMsg
	pop	DX
	mov	SI, Offset $Fail
	mov	CX, 18
	add	CX, DX
	call	.Msg

	jmp	ISearchLoop



; <ESC>, <DEL>, <REV>, <ISE>
Getstring:
	push	DX
GetString0:
	call	.InCH
	jz	GetString0
	pop	DX

	cmp	AL, 8	; ^H
	je	ISMinus
	cmp	AL, 18  ; ^R
	je	ISR
	cmp	AL, 19  ; ^S
	je	ISI
	cmp	AL, LF	; ^J
	je	GetString1
	cmp	AL, TAB	; ^I
	je	GetString1
	cmp	AL, 17	; ^Q
	je	QuoteOne
	cmp	AL, ' '
	jb	ISExit
GetString1:
	call	.CAPS
	mov	BX, DX
	mov	CS:[BX+Offset $SString], AL
	inc	DX
	jmp	GSR

ISMinus:cmp	DX, 0
	je	ISExit
	dec	DX
	dec	DS:BCB.FCursor
	mov	CS:$Failed, 0
	jmp	GSR

ISI:	cmp	DX, 0
	je	.SSSS
	inc	DS:BCB.FCursor
	jmp	GSR
.SSSS:  mov	DL, CS:$LastLength
	xor	DH, DH
	jmp	GSR


ISR:	cmp	DX, 0
	je	RSearch
	jmp	RSearch1

ISExit: mov	CS:$LastLength, DL
	mov	CS:$Failed, 0
	mov	DS:BCB.FCursor, BP
	push	AX
	call	.CLRMsg
	pop	AX

	pop	BP			; kill return address
	pop	BX
	pop	BX			; adjust stack ptr to return from case

	mov	CS:$Repeat, 0
	call	FParse0
	or	AH, AH
	jnz	GotRealcommand

	jmp	MainScreenDraw

GotRealcommand:
	jmp	Maincommand

QuoteOne:
	push	DX			; do avoid all further checking
Q1:	call	.InCH
	jz	Q1
	pop	DX
	jmp	GetString1

ISearch ENDP

;---------------------------------------------------------------------------
RSearch PROC	NEAR

	xor	DX, DX
	mov	BP, DS:BCB.FCursor
	mov	CS:$Header, 'R'
	mov	AX, ScreenSegment
	mov	ES, AX
	call	.CLRMsg
	mov	SI, Offset $Header
	mov	CX, 10
	call	.Msg

RSearchLoop:
	jmp	GetStringR
GSRR:	cmp	CS:$Failed, 0
	jne	RSFail
	mov	CS:$LastLength, 0 ; chance for ^R over
RSearch1:
	mov	CS:$Header, 'R'
	mov	SI, DS:BCB.FCursor
	call	.Bind
	or	AH, AH
	jnz	RSFail


RSOK:	mov	DS:BCB.FCursor, SI
	call	.SScreen
	call	.CLRMsg
	mov	SI, Offset $Header
	mov	CX, 10
	add	CX, DX
	call	.Msg
	mov	CS:$Failed, 0
	jmp	RSearchLoop

RSFail: mov	CS:$Failed, 0FFh
	push	DX
	call	Sound
	call	.CancelMacro
	call	.CLRMsg
	pop	DX
	mov	SI, Offset $Fail
	mov	CX, 18
	add	CX, DX
	call	.Msg

	jmp	RSearchLoop



; <ESC>, <DEL>, <REV>, <ISE>
GetstringR:
	push	DX
GetStringR0:
	call	.InCH
	jz	GetStringR0
	pop	DX

	cmp	AL, 8	; ^H
	je	RSMinus
	cmp	AL, 19  ; ^S
	je	RSI
	cmp	AL, 18  ; ^R
	je	RSR
	cmp	AL, LF	; ^J
	je	GetStringR1
	cmp	AL, TAB	; ^I
	je	GetStringR1
	cmp	AL, 17	; ^Q
	je	QuoteOne1
	cmp	AL, ' '
	jae	GetStringR1
	jmp	ISExit
GetStringR1:
	call	.CAPS
	mov	BX, DX
	mov	CS:[BX+Offset $SString], AL
	inc	DX
	jmp	GSRR

QuoteOne1:
	push	DX			; do avoid all further checking
Q11:	call	.InCH
	jz	Q11
	pop	DX
	jmp	GetStringR1

RSMinus:cmp	DX, 0
	jne	RSM1
	jmp	ISExit
RSM1:	dec	DX
	inc	DS:BCB.FCursor
	mov	CS:$Failed, 0
	jmp	GSRR

RSR:	cmp	DX, 0
	je	.SSSS1
	dec	DS:BCB.FCursor
	jmp	GSRR
.SSSS1: mov	DL, CS:$LastLength
	xor	DH, DH
	jmp	GSRR


RSI:	cmp	DX, 0
;	je	ISearch
;	jne	ISearch1
	je	RSI1
	jmp	ISearch1
RSI1:	jmp	ISearch

RSearch ENDP

;---------------------------------------------------------------------------
.SScreen	PROC	Near

	push	DX
	call	.Screen
	call	FModeline
	pop	DX
	mov	BP, DS:BCB.FCursor
	ret

.SScreen	ENDP

;---------------------------------------------------------------------------
Wildcard	EQU	10	; ^J
.FIND	PROC	Near
; SI -> Start of Search	DX  -> # characters in Searchbuffer

	dec	SI
.FNew:  xor	BX, BX  ; last try unsuccessful, try one character further
	mov	DI, Offset $SString
	inc	SI
.FMay:  cmp	SI, DS:BCB.FEnd  ; all characters so far match
	jae	.FErr
	mov	AH, CS:[DI+BX]
	cmp	AH, Wildcard
	je	.F1Mat
	mov	AL, DS:[SI+BX]
	call	.CAPS
	cmp	AL, AH
	jne	.FNew
.F1Mat: inc	BX		; one character matches
	cmp	BX, DX
	jb	.FMay

.FFound:mov	AH, 0
	ret
.FErr:  mov	AH, 0FFh
	ret
.Find	ENDP

;....................
.BIND	PROC	Near
; SI -> Start of Search	DX  -> # characters in Searchbuffer

	inc	SI
.BNew:  xor	BX, BX  ; last try unsuccessful, try one character further
	mov	DI, Offset $SString
	dec	SI
.BMay:  cmp	SI, 100h  ; all characters so far match
	jb	.BErr
	mov	AH, CS:[DI+BX]
	cmp	AH, Wildcard
	je	.B1Mat
	mov	AL, DS:[SI+BX]
	call	.CAPS
	cmp	AL, AH
	jne	.BNew
.B1Mat: inc	BX		; one character matches
	cmp	BX, DX
	jb	.BMay

.BFound:mov	AH, 0
	ret
.BErr:  mov	AH, 0FFh
	ret
.Bind	ENDP

.CancelMacro	PROC	NEAR
	cmp	CS:MacroInvocation, TRUE
	je	.CYes
	cmp	CS:MacroDefinition, TRUE
	je	.CYes
	cmp	CS:MacArg, 0
	jne	.CYes
	cmp	CS:$Repeat, 0
	jne	.CYes
	ret

MacCancel	db	'*** Cancelled Macro ***'
.CYes:	mov	CS:$LastLength, DL
	mov	CS:$Failed, 0
	mov	DS:BCB.FCursor, BP
	call	.CLRMsg

	mov	SI, Offset MacCancel
	mov	CX, 23
	jmp	.Error0
.CancelMacro	ENDP
PROGRAM ENDS
	END
