include	clib.inc
include	iost.inc
include	string.inc
include	conio.inc

	public	continuesearch
	public	notfoundmsg
	extrn	IDD_Search:dword
	extrn	searchstring: byte
ifdef DEBUG
	public	searchtxt
	public	seekbx
endif

_DATA	SEGMENT

cp_search	db 'Search',0
cp_notfoundmsg	db "Search string not found: '%s'",0
cp_stlsearch	db 'Search for the string:',0

hexstring	db 128 dup(?)
hexstrlen	dw 0

_DATA	ENDS

_TEXT	SEGMENT

ioseek proc
	lodm STDI.ios_bb	; current offset
	mov cx,STDI.ios_flag
	and STDI.ios_flag,not (IO_SEARCHSET or IO_SEARCHCUR)
	.if cx & IO_SEARCHSET
	    sub ax,ax
	    cwd
	.elseif	!(cx & IO_SEARCHCUR)
	    add ax,1		; offset++ (continue)
	    adc dx,0
	.endif
	mov di,ax
	mov bp,dx
	invoke oseek, dx::ax, SEEK_SET
	ret
ioseek endp

seekbx proc
	.if bx <= STDI.ios_i
	    sub di,bx
	    sbb bp,0
	    sub STDI.ios_i,bx
	    ret
	.endif
	push si
	mov si,bx
	.repeat
	    call oungetc
	    sub di,1
	    sbb bp,0
	    dec si
	.until !si
	pop si
	ret
seekbx endp

lodhex proc
	mov al,[si]
	test al,al
	jz lodhex_end
	inc si
	cmp al,'0'
	jb lodhex
	cmp al,'9'
	jbe lodhex_ok
	or al,20h
	cmp al,'f'
	ja lodhex
	sub al,27h
    lodhex_ok:
	sub al,'0'
	or si,si
    lodhex_end:
	ret
lodhex endp

searchfound proc
	mov ax,si
	sub ax,dx
	inc ax
	sub di,ax
	sbb bp,0
	mov ax,di
	mov dx,bp
	or  di,1
	ret
searchfound endp

searchhex proc
	push bp
	push si
	push di
	call ioseek
	jz searchhex_end
	xor cx,cx
	mov si,offset searchstring
	mov bx,offset hexstring
    searchhex_xtol:
	call lodhex
	jz searchhex_hexl
	mov ah,al
	call lodhex
	jnz searchhex_mkb
	xchg al,ah
    searchhex_mkb:
	shl ah,4
	or al,ah
	mov [bx],al
	inc bx
	inc cx
	jmp searchhex_xtol
    searchhex_found:
	call searchfound
    searchhex_end:
	pop di
	pop si
	pop bp
	ret
    searchhex_hexl:
	mov hexstrlen,cx
    searchhex_scan:
	mov dl,hexstring
	mov cx,STDI.ios_l
	  @@:
	    call ogetc
	    jz searchhex_end
	    add di,1	; inc offset
	    adc bp,0
	    mov ah,al
	    sub ah,10
	    cmp ah,1
	    adc cx,0	; inc line
	    cmp al,dl
	    jne @B
	mov STDI.ios_l,cx
	mov si,offset hexstring
    searchhex_cmp:
	call ogetc
	jz searchhex_end
	add di,1
	adc bp,0
	inc si
	mov dx,offset hexstring
	mov cx,si
	sub cx,dx
	cmp cx,hexstrlen
	je searchhex_found
	cmp al,[si]
	je searchhex_cmp
	mov bx,si
	sub bx,dx
	call seekbx
	jmp searchhex_scan
searchhex endp

search	proc
	sub ax,ax
	.if searchstring != al
	    .if STDI.ios_flag & IO_SEARCHHEX
		jmp searchhex
	    .endif
	    jmp searchtxt
	.endif
	ret
search	endp

searchtxt proc
	push bp
	push si
	push di
	call ioseek
	jz searchtxt_end
    searchtxt_scan:
	sub cx,cx
	.if STDI.ios_flag & IO_SEARCHCASE
	    mov dl,searchstring
	  @@:
	    call ogetc
	    jz searchtxt_end
	    add di,1	; inc offset
	    adc bp,0
	    cmp	al,10
	    je searchtxt_l12
    	searchtxt_l11:
	    cmp al,dl
	    jne @B
	.else
	    mov al,searchstring
	    mov dl,al
	    sub al,'a'
	    cmp al,'Z' - 'A' + 1
	    sbb al,al
	    and al,'a' - 'A'
	    xor dl,al
	  @@:
	    call ogetc
	    jz searchtxt_end
	    add di,1
	    adc bp,0
	    cmp	al,10
	    je searchtxt_l22
    	searchtxt_l21:
	    mov ah,al
	    sub al,'a'
	    cmp al,'Z' - 'A' + 1
	    sbb al,al
	    and al,'a' - 'A'
	    xor ah,al
	    cmp ah,dl
	    jne @B
	.endif
	add STDI.ios_l,cx
	mov si,offset searchstring
    searchtxt_cmp:
	call ogetc
	jz searchtxt_end
	add di,1
	adc bp,0
	inc si
	mov dx,offset searchstring
	mov cl,al
	mov al,[si]
	test al,al
	jz searchtxt_found
	cmp al,cl
	je searchtxt_cmp
	.if !(STDI.ios_flag & IO_SEARCHCASE)
	    mov ah,al
	    sub al,'a'
	    cmp al,'Z' - 'A' + 1
	    sbb al,al
	    and al,'a' - 'A'
	    xor ah,al
	    cmp ah,cl
	    je searchtxt_cmp
	.endif
	mov bx,si
	sub bx,dx
	call seekbx
	jmp searchtxt_scan
    searchtxt_found:
	call searchfound
    searchtxt_end:
	pop di
	pop si
	pop bp
	ret
    searchtxt_l12:
    	inc cx
	jmp searchtxt_l11
    searchtxt_l22:
    	inc cx
	jmp searchtxt_l21
searchtxt endp

notfoundmsg proc
	mov	cp_notfoundmsg+24,' '
	push	ds
	push	offset searchstring
	call	strlen
	.if ax >= 29
	    mov cp_notfoundmsg+24,10
	.endif
	push	ds
	push	offset searchstring
	mov	dx,offset cp_notfoundmsg
	mov	ax,offset cp_search
	call	@stdmsg
	add	sp,4
	ret
notfoundmsg endp

continuesearch proc DIST
	push	bp
	sub	sp,160
	mov	bp,sp
	sub	ax,ax
	.if searchstring
	    invoke wcpushst,ss::bp,addr cp_stlsearch
	    scputs@ 24,_scrrow,0,80-24,ds,offset searchstring
	    invoke oseekl,STDI.ios_bb,SEEK_SET
	    .if ax
		.if STDI.ios_flag & IO_SEARCHHEX
		    call searchhex
		.else
		    call searchtxt
		.endif
		.if !ZERO?
		    stom STDI.ios_bb
		    mov ax,1
		    jmp @F
		.endif
	    .endif
	    call notfoundmsg
	    xor ax,ax
	  @@:
	    push ax
	    invoke wcpopst, ss::bp
	    pop ax
	.endif
	add	sp,160
	pop	bp
	ret
continuesearch endp

_TEXT	ENDS

PPROC	osearch, h:word, fsize:dword, buf:dword, bsize:word, flag:word
	mov	bx,h
	mov	STDI.ios_file,bx
	mov	ax,4201h
	xor	cx,cx
	xor	dx,dx
	int	21h
	jc	osearch_err
	stom	STDI.ios_bb
	xor	ax,ax
	mov	STDI.ios_c,ax
	mov	STDI.ios_i,ax
	movmw	STDI.ios_size,bsize
	movmx	STDI.ios_bp,buf
	mov	ax,flag
	or	ax,IO_SEARCHCUR
	mov	STDI.ios_flag,ax
	call	search
	jnz	osearch_end
    osearch_err:
	mov	ax,-1
	cwd
    osearch_end:
	mov	cx,STDI.ios_l
	ret
PEND	osearch

PPROC	cmsearchidd, sflag:word
	push	si
	invoke	rsopen, IDD_Search
	jz	cmsearchidd_nul
	push	dx
	push	ax
	pushm	IDD_Search
	push	dx
	push	ax
	push	dx
	push	ax
	mov	es:[bx+1*16].to_count,128 shr 4
	mov	word ptr es:[bx+1*16].to_data,offset searchstring
	mov	word ptr es:[bx+1*16].to_data+2,ds
	mov	ax,sflag
	mov	dl,_O_FLAGB
	test	ax,IO_SEARCHCASE
	jz	cmsearchidd_hex?
	or	es:[bx+2*16],dl
    cmsearchidd_hex?:
	test	ax,IO_SEARCHHEX
	jz	cmsearchidd_cur?
	or	es:[bx+3*16],dl
    cmsearchidd_cur?:
	mov	dl,_O_RADIO
	test	ax,IO_SEARCHCUR
	jz	cmsearchidd_rset
	or	es:[bx+6*16],dl
	jmp	cmsearchidd_event
    cmsearchidd_nul:
	xor	ax,ax
	jmp	cmsearchidd_end
    cmsearchidd_rset:
	or	es:[bx+7*16],dl
    cmsearchidd_event:
	call	dlinit
	call	rsevent
	test	ax,ax
	jz	cmsearchidd_nul
	mov	ax,sflag
	and	ax,not IO_SEARCHMASK
	mov	dl,_O_FLAGB
	test	es:[bx+2*16],dl
	jz	cmsearchidd_hex
	or	ax,IO_SEARCHCASE
    cmsearchidd_hex:
	test	es:[bx+3*16],dl
	jz	cmsearchidd_cur
	or	ax,IO_SEARCHHEX
    cmsearchidd_cur:
	test	byte ptr es:[bx+6*16],_O_RADIO
	jz	cmsearchidd_set
	or	ax,IO_SEARCHCUR
	jmp	cmsearchidd_toend
    cmsearchidd_set:
	or	ax,IO_SEARCHSET
    cmsearchidd_toend:
	mov	dx,ax
	xor	ax,ax
	cmp	searchstring,al
	je	cmsearchidd_end
	inc	ax
    cmsearchidd_end:
	mov	si,dx
	call	dlclose
	mov	ax,dx
	mov	dx,si
	test	ax,ax
	pop	si
	ret
PEND	cmsearchidd

PPROC	cmdsearch, offs:dword
	xor	ax,ax
	cmp	ax,word ptr offs+2
	jne	cmdsearch_00
	cmp	word ptr offs,16
	jb	cmdsearch_end
    cmdsearch_00:
	push	STDI.ios_flag
	call	cmsearchidd
	jz	cmdsearch_end
	mov	STDI.ios_flag,dx
	and	dx,IO_SEARCHCUR or IO_SEARCHSET
	push	dx
	call	continuesearch
	pop	dx
	or	STDI.ios_flag,dx
    cmdsearch_end:
	ret
PEND	cmdsearch

	END
