Metropoli BBS
VIEWER: search.asm MODE: TEXT (ASCII)
; SEARCH.ASM for E32 - Copyright (C) 1994 Douglas Herr
;  all rights reserved

include	model.inc

public	search, search_again, replace

extrn	locate:near
extrn	working:near		; 'Working' message
extrn	display_screen:near, display_current:near
extrn	close_space:near, open_space:near
extrn	edit_filename:near
extrn	rowcount:near

extrn	tedit:near
extrn	strlen:near
extrn	cursoron:near
extrn	keyifwaiting:near, tprintce:near
extrn	$strstr:near
extrn	$stristr:near

temp_string	equ	[ebp-64]

include	dataseg.inc

extrn	filesiz:dword		; size of file loaded in XMS memory

extrn	cursor:dword, inverse:byte, rows:byte
extrn	dirty_bits:byte
extrn	zero_sel:word
extrn	first_row:byte

extrn	key_status:byte
kbdstat	db 0
find_mess	db " Find: ",0

replace_msg	db ' replace? (Yes/No/All)',0
replace_prompt	db ' Replace with: ',0
replace_mode	db 0
search_len	dw 0
replace_len	dw 0
bytes_to_add	dw 0
was_replaced	db 0

save_offset	dd offset init_and_save
replace_ptr	dd ?
search_ptr	dd ?

extrn	cur_posn:word
extrn	breakflag:byte
extrn	undo_length:word
extrn	count_start:dword
count_bytes	equ	dword ptr count_start+4
@curseg	ends

include	codeseg.inc
search_again	label proc
	enter	64,0
	call	save_offset

	mov	esi,search_ptr
	movzx	ecx,search_len
	cmp	byte ptr [esi],0
	jne	short s0
	jmp	short _ss
;
; This subroutine searches for a string
;
search	proc	near
	enter	64,0
	call	save_offset		; save cursor offset
	jc	exit
_ss:
; copy saved search string to temp_string
	mov	esi,search_ptr
	call	copy_to_temp_string
	call	get_search_string
	mov	kbdstat,dl		; save keyboard status
	mov	search_len,cx

	cmp	ax,27
	je	exit		; exit if ESC pressed

; copy search string to storage area
	mov	edi,search_ptr
	push	edi
	call	copy_from_temp_string
	pop	esi			; search_ptr

	cmp	ecx,1
	jc	short exit

s0:	call	working			; print 'Working' message

	mov	edi,cursor
	inc	edi			; start search one past cursor
	push	fs
	pop	es
	mov	ebx,ecx
	mov	edx,filesiz
	sub	edx,edi			; bytes in file to search
	jbe	short exit

	test	kbdstat,3		; Shift key pressed?
	jz	short s5
	call	$stristr
	jmp	short s6
s5:
	call	$strstr
s6:
	jc	short exit
	add	eax,cursor
	inc	eax
	mov	cursor,eax

; save bytes to search for rows
	mov	ecx,eax
	sub	ecx,count_start
	mov	count_bytes,ecx

	mov	dh,rows
	sub	dh,first_row
	shr	dh,1
	add	dh,first_row
	mov	esi,eax			; cursor
	call	locate
	or	dirty_bits,1
	call	rowcount
exit:
	clc
	leave
	ret

search	endp

replace_proc	equ	[ebp-68]

replace	proc	near
	enter	68,0
	call	save_offset
r2:	mov	esi,search_ptr
	call	copy_to_temp_string
	call	get_search_string	; get string to replace
	mov	kbdstat,dl		; save keyboard status
	cmp	ax,27
	je	replace_exit		; exit if ESC pressed
	test	ecx,ecx
	jnz	short r1
	jmp	replace_exit
r1:
	mov	search_len,cx
	mov	edi,search_ptr
	call	copy_from_temp_string
	mov	esi,replace_ptr
	call	copy_to_temp_string
	call	get_replace_string
	mov	replace_mode,dl		; save keyboard status
	cmp	ax,27
	je	r2
	jcxz	r1

	mov	replace_len,cx
	sub	cx,search_len		; bytes to add
					; negative if file is shortened
					; zero if len(search) = len(replace)
	mov	eax,offset @curseg:same_length
	jz	short r1a
	mov	eax,offset @curseg:increase
	jns	short r1a
	mov	eax,offset @curseg:decrease
	neg	cx

r1a:	mov	replace_proc,eax
	mov	bytes_to_add,cx

	mov	edi,replace_ptr
	call	copy_from_temp_string
	mov	breakflag,0		; zero the ^C flag

r:
	call	search_again		; search for next occurance
	test	dirty_bits,1		; flag set if string found
	jz	short replace_exit	;  exit if not found
	call	display_screen		; update screen
	mov	dx,cur_posn
	call	cursoron
	shr	breakflag,1
	jc	short replace_exit
	cmp	replace_mode,0
	jne	short _replace_string
	lea	esi,replace_msg
	mov	dh,rows
	inc	dh
	xor	dl,dl
	mov	ah,inverse
	call	tprintce
r3:	shr	breakflag,1
	jc	short replace_exit
	call	keyifwaiting
	test	ax,ax
	jz	r3
	shr	ah,1			; filter out extended keycodes
	jc	r3
	cmp	al,27
	je	short replace_exit
	and	al,0FFh-32		; upper case
	cmp	al,'Y'
	je	short _replace_string
	cmp	al,'N'
	je	r
	cmp	al,'A'
	jne	r3
	not	replace_mode		; change to continuous
					; & fall into _replace_string
_replace_string:
	call	[replace_proc]
	call	display_current
	and	dirty_bits,11111110b
	jmp	r

replace_exit:
	test	was_replaced,1
	jz	short r_exit
	mov	dh,rows
	sub	dh,first_row
	shr	dh,1
	add	dh,first_row
	mov	esi,cursor			; cursor
	call	locate
	or	dirty_bits,1

r_exit:
	clc
	leave
	ret
replace	endp

;
; SUBROUTINES
;
get_replace_string:
	lea	esi,replace_prompt
	jmp	short g0

get_search_string:
	lea	esi,find_mess
g0:	call	edit_filename

	mov	es,zero_sel
	mov	dl,es:[417h]		; get kbd status
	and	dl,11b			; DL <> 0 if shift key pressed
near_ret:
	ret


;
; replace search string at cursor
; called indirectly by replace_proc
;
decrease:
; net file size decrease if len(search) > len(replace)
	movzx	eax,bytes_to_add	; remove EAX bytes from file
	call	close_space
	jmp	short same_length

increase:
; net file size increase if len(search) < len(replace)
	movzx	eax,bytes_to_add
	call	open_space

same_length:
; copy replacement string to file
	mov	esi,replace_ptr
	movzx	ecx,replace_len
	mov	edi,cursor
	add	cursor,ecx
	push	fs
	pop	es
	cld
	rep	movsb
	mov	was_replaced,1
	or	dirty_bits,10000000b
	ret


;
; initialize search_ptr and replace_ptr
init_and_save:
	mov	save_offset,offset @curseg:save_only
	mov	ebx,128
	sys	GetMemNear
	mov	search_ptr,esi
	mov	byte ptr [esi],0
	add	esi,64
	mov	replace_ptr,esi
	mov	byte ptr [esi],0
;
; save absolute cursor offset for count_start
;
save_only:
	mov	eax,cursor
	mov	count_start,eax
	cld
	ret

copy_to_temp_string:
	lea	edi,temp_string
	push	ss
	pop	es
	mov	ecx,64/4
	rep	movsd
	push	ds
	pop	es
	ret

copy_from_temp_string:
	lea	esi,temp_string
	push	ds
	push	es
	push	ecx
	push	ds
	pop	es
	push	ss
	pop	ds
	cld
	mov	ecx,64/4
	rep	movsd
	pop	ecx
	pop	es
	pop	ds
	ret

@curseg	ends
	end
[ RETURN TO DIRECTORY ]