ifdef DEBUG
  __TVEXE__ equ 1
endif
include clib.inc
include malloc.inc
include dos.inc
include dir.inc
include io.inc
include iost.inc
include time.inc
include filter.inc
include progress.inc
include string.inc
include syserrls.inc
include	conio.inc
include	mouse.inc
include	keyb.inc
include	stdio.inc
include	tinfo.inc
include version.inc
include	tview/tview.inc
include	ff/ff.inc

	public	_stklen
	public	tvflag
	public	fsflag
	public	teflag
	public	telsize
	public	tepages
	public	configpath
	public	configfile
	public	searchstring
	public	replacestring

externdef	_argc:word
externdef	_argv:dword
externdef	format_u:byte
externdef	format_lu:byte
externdef	IDD_FFFindFile:dword
externdef	IDD_FFHelp:dword
externdef	IDD_DZMKList:dword
externdef	IDD_DZMKListHelp:dword
externdef	IDD_OperationFilters:dword
filter_wblk	proto dist pascal :dword

S_MKLST		STRUC
mkl_macro	db ?	; use output macro
mkl_append	db ?	; add to list or create new
mkl_unix	db ?	; convert to unix
mkl_excl_cd	db ?	; use local directory
mkl_excl_drv	db ?	; use drive in directory
mkl_mask	db ?	; add mask to directory\[*.*]
mkl_offspath	dw ?	; length of local directory
mkl_offset	dd ?	; search offset from findfile
mkl_handle	dw ?
mkl_count	dd ?	; total file count in list
S_MKLST		ENDS

ID_FILE = 13

OF_MASK	= 14*16
OF_PATH	= 15*16
OF_SSTR	= 16*16
OF_SUBD	= 17*16
OF_CASE	= 18*16
OF_HEXA	= 19*16
OF_FIND	= 20*16
OF_FILT	= 21*16
OF_SAVE	= 22*16
OF_QUIT	= 23*16
OF_MSUP	= 24*16
OF_MSDN	= 25*16
OF_GCMD = OF_MSUP

OUTPUT_BINARY	= 0	; Binary dump (default)
OUTPUT_TEXT	= 1	; Convert tabs, CR/LF
OUTPUT_LINE	= 2	; Convert tabs, break on LF

_DATA	SEGMENT

cp_info	label byte
	db	'Find File Version ',VERS?,' Copyright (c) 2012 Hjort Nidudsson',13,10
size_info = $ - offset cp_info
_stklen		dw 3000h

DLG_FindFile	dd ?
FCB_FindFile	dw ?

GCMD_search	label word
GCMD KEY_F2,	event_mklist
GCMD KEY_F3,	event_view
GCMD KEY_F4,	event_edit
GCMD KEY_F5,	event_filter
GCMD KEY_F6,	event_toggle_hex
GCMD KEY_F7,	event_find
GCMD KEY_F8,	event_delete
GCMD KEY_F10,	event_toggle_format
GCMD KEY_DEL,	event_delete
GCMD KEY_ALTX,	event_exit
		dw	0

ff_basedir	dd ?
cp_stdmask	db '*.*',0
cp_search	db 'Search',0
option_q	db 0
ff_cfg		db 'ff.cfg',0
ff_ini		db 'ff.ini',0
arg_file	dd 0
arg_offset	dd 0
arg_size	dd 0
configpath	db WMAXPATH dup(0)
configfile	db WMAXPATH dup(0)

tvflag		db _TV_HEXOFFSET or _TV_USEMLINE or _TV_USESLINE
fsflag		db IO_SEARCHSUB
ffflag		db 2
teflag 		dw _T_TEDEFAULT
telsize 	dw 256
tepages 	dw 64
searchstring	db 128 dup(0)
replacestring	db 128 dup(?)
filelist	db 'filelist.bat',0
		db 80-13 dup(0)
formatlist	db '%f\n',0
		db 128-5 dup(0)
findmask	db '*.*',0
		db 270-4 dup(0)
findpath	db 270 dup(0)
opfilter	S_FILT <-1,0,0,0,0,'*.*',0>
mklist		S_MKLST	<?,?,?,?,?,?,?,-1,?>
tv_clversion	dw CLVERSION
tv_classsize	dw CLCOUNT
tv_classrow	dw CLCOUNT
tv_class	S_CLASS CLCOUNT dup(<'byte',1,CLTYPE_BYTE,CLFORM_HEX>)
size_config	= $ - offset tvflag

filelist_bat	dd DGROUP:filelist
format_lst	dd DGROUP:formatlist
findfilemask    dd DGROUP:findmask
findfilepath    dd DGROUP:findpath
doskey_bindex	db ?
doskey_isnext	db ?

filter		dd 0

$BACK db '\'		; 5C
BACK$ db '\',0		; '\'
$SIGN db '\'		; 25
SIGN$ db '%',0		; '%'
$TAB9 db '\t',0		; 09
$CRLF db '\n',0		; 0D 0A
TAB9$ db 9,0
CRLF$ db 0Dh,0Ah
NULL$ db 0
$FILE db '%f',0		; File name
$PATH db '%p',0		; Path part of file
$CURD db '%cd',0	; Current directory
$HOME db '%dz',0	; Doszip directory
$name db '%n',0		; Name part of file
$TYPE db '%ext',0	; Extension of file
$SSTR db '%s',0		; Search string
$FCID db '%id',0	; File index or loop counter
$OFFS db '%o',0		; Offset string
$TMP1 db 7,1,0		; unlikely combination 1 '\\'
$TMP2 db 7,2,0		; unlikely combination 2 '\%'

cp_ini label byte
incbin	<tview/default.ini>
incbin	<tedit/default.ini>
	db 0
size_ini = $ - offset cp_ini

_DATA	ENDS

_TEXT	SEGMENT

expand_macro proc
	push ax
	push bp	; buf
	push ax
	push dx	; old
	push ax
	push cx	; new
	push ax
	push dx
	call strlen
	push ax	; len
	call strxchg
	ret
expand_macro endp

mklistadd proc		; dx:ax=file name
	push bp
	sub sp,WMAXPATH*3
	mov bp,sp
	push si
	push di
	mov bx,ax
	xor ax,ax
	mov cx,ax
	incm mklist.mkl_count
	.if mklist.mkl_excl_drv != al
	    mov es,dx
	    .if byte ptr es:[bx+1] == ':'
		add cx,2
	    .endif
	.endif
	add bx,cx
	.if mklist.mkl_excl_cd != al
	    add bx,mklist.mkl_offspath
	    sub bx,cx
	.endif
	.if mklist.mkl_unix != al
	    invoke dostounix, dx::bx
	    mov bx,ax
	.endif
	lea di,[bp+WMAXPATH*2]
	invoke strcpy, ss::di, dx::bx
	invoke strcpy, ss::bp, format_lst
	.if mklist.mkl_macro != 1
	    invoke strcpy, dx::ax, dx::di
	    jmp mklistadd_nomacro
	.endif
	mov ax,dx
	mov dx,offset $BACK	; '\\'
	mov cx,offset $TMP1	; --> 07 01
	call expand_macro
	mov ax,ss
	mov dx,offset $CRLF	; '\n'
	mov cx,offset CRLF$	; --> 0D 0A
	call expand_macro
	mov ax,ss
	mov dx,offset $TAB9	; '\t'
	mov cx,offset TAB9$	; --> 09
	call expand_macro
	mov ax,ss
	mov dx,offset $SIGN ; '\%'
	mov cx,offset $TMP2	; --> 07 02
	call expand_macro
	mov ax,ss
	mov dx,offset $TMP1	; 07 01
	mov cx,offset BACK$	; --> '\'
	call expand_macro
	mov ax,ss
	mov dx,offset $HOME
	mov cx,offset configpath
	call expand_macro
	mov ax,ss
	mov dx,offset $FILE
	mov cx,di
	call expand_macro
	invoke strfn, ss::di
	mov si,ax
	invoke strrchr, dx::ax, '.'
	mov di,ax
	.if ZERO?
	    mov ax,offset NULL$
	.endif
	mov cx,ax
	mov ax,ss
	mov dx,offset $TYPE
	call expand_macro
	sub ax,ax
	.if ax != di
	    mov [di],al
	.endif
	mov cx,si
	mov ax,ss
	mov dx,offset $name
	call expand_macro
	lea di,[bp+WMAXPATH*2]
	.if di != si
	    mov cx,di
	    xor ax,ax
	    mov [si-1],al
	.else
	    mov cx,offset NULL$
	.endif
	mov ax,ss
	mov dx,offset $PATH
	call expand_macro
	xor ax,ax
	mov cx,di
	mov bx,di
	add bx,mklist.mkl_offspath
	.if bx != cx
	    dec bx
	.endif
	mov [bx],al
	mov ax,ss
	mov dx,offset $CURD
	call expand_macro
	mov ax,ss
	mov dx,offset $SSTR
	mov cx,offset searchstring
	call expand_macro
	mov ax,word ptr mklist.mkl_count
	dec ax
	push ax
	mov ax,offset format_u
	mov dx,ss
	mov bx,di
	call @sprintf
	add sp,2
	mov ax,ss
	mov dx,offset $FCID
	mov cx,di
	call expand_macro
	pushm mklist.mkl_offset
	mov ax,offset format_lu
	mov dx,ss
	mov bx,di
	call @sprintf
	add sp,4
	mov ax,ss
	mov dx,offset $OFFS
	mov cx,di
	call expand_macro
	mov ax,ss
	mov dx,offset $TMP2 ; 07 02 00
	mov cx,offset SIGN$ ; --> '%'
	call expand_macro
    mklistadd_nomacro:
	invoke strlen, ss::bp
	.if func(oswrite, mklist.mkl_handle, ss::bp, ax)
	    mov ax,0
	    .if mklist.mkl_macro != 1
		invoke oswrite, mklist.mkl_handle, addr CRLF$, 2
		sub ax,2
		.if ax
		    inc ax
		.endif
	    .endif
	.else
	   inc ax
	.endif
    mklistadd_end:
	or ax,ax
	pop di
	pop si
	add sp,WMAXPATH*3
	pop bp
	ret
mklistadd endp

MKLID_LIST	= 1*16
MKLID_APPEND	= 2*16
MKLID_FORMAT	= 3*16
MKLID_UNIX	= 4*16
MKLID_EXLCD	= 5*16
MKLID_EXLDRV	= 6*16
MKLID_FILTER	= 9*16

mklevent_HELP proc dist
	invoke rsmodal, IDD_DZMKListHelp
	ret
mklevent_HELP endp

mklevent_FILTER proc dist
	invoke filter_edit, addr opfilter, 0
	les bx,tdialog
	mov bx,es:[bx+4]
	add bx,0A1Ch
	mov cx,1
	mov al,' '
	.if word ptr filter
	    mov ax,7
	.endif
	call @scputw
	mov ax,_C_NORMAL
	ret
mklevent_FILTER endp

mklistidd proc pascal public uses si di
local DLG_DZMKList:dword
	.if func(rsopen, IDD_DZMKList)
	    stom DLG_DZMKList
	    fpmov es:[bx.to_proc+MKLID_FILTER],mklevent_FILTER
	    mov si,word ptr es:[bx+MKLID_LIST].to_data+2
	    mov di,word ptr es:[bx+MKLID_LIST].to_data
	    mov al,mklist.mkl_append
	    and al,_O_FLAGB
	    or  es:[bx+MKLID_APPEND],al
	    mov al,mklist.mkl_unix
	    and al,_O_FLAGB
	    or  es:[bx+MKLID_UNIX],al
	    mov al,mklist.mkl_excl_cd
	    and al,_O_FLAGB
	    or  es:[bx+MKLID_EXLCD],al
	    mov al,mklist.mkl_excl_drv
	    and al,_O_FLAGB
	    or  es:[bx+MKLID_EXLDRV],al
	    invoke strcpy, es:[bx+MKLID_FORMAT].to_data, format_lst
	    invoke strcpy, si::di, filelist_bat
	    xor ax,ax
	    mov word ptr mklist.mkl_offset+2,ax
	    mov word ptr mklist.mkl_offset,ax
	    LPUSH cs
	    push offset mklevent_HELP
	    call thelp_set
	    invoke dlinit, DLG_DZMKList
	    invoke dlevent, DLG_DZMKList
	    call thelp_pop
	    .if ax
		sub ax,ax
		mov word ptr mklist.mkl_count,ax
		mov word ptr mklist.mkl_count+2,ax
		mov mklist.mkl_macro,1
		mov al,es:[bx+MKLID_APPEND]
		and al,_O_FLAGB
		mov mklist.mkl_append,al
		mov al,es:[bx+MKLID_UNIX]
		and al,_O_FLAGB
		mov mklist.mkl_unix,al
		mov al,es:[bx+MKLID_EXLCD]
		and al,_O_FLAGB
		mov mklist.mkl_excl_cd,al
		mov al,es:[bx+MKLID_EXLDRV]
		and al,_O_FLAGB
		mov mklist.mkl_excl_drv,al
		invoke strcpy, format_lst, es:[bx+MKLID_FORMAT].to_data
		invoke strcpy, filelist_bat, si::di
		invoke dlclose, DLG_DZMKList
		.if mklist.mkl_append
		    invoke filexist, si::di
		    .if ax == 1
			.if func(openfile, si::di, M_WRONLY, A_OPEN)
			    mov mklist.mkl_handle,ax
			    invoke lseek, ax, 0, SEEK_END
			    mov ax,1
			.endif
			jmp @F
		    .elseif ax == 2
			sub ax,ax
			jmp @F
		    .endif
		.endif
	    .else
		invoke dlclose, DLG_DZMKList
		sub ax,ax
		jmp @F
	    .endif
	    invoke ogetouth, si::di
	    mov mklist.mkl_handle,ax
	    test ax,ax
	.endif
      @@:
	ret
mklistidd endp

whilekeyalt proc	; Delay Alt-Key on exit
	les bx,keyshift
	mov bl,es:[bx]
	test bl,KEY_ALT
	jnz whilekeyalt
	ret
whilekeyalt endp

getcurobj proc
	mov bx,FCB_FindFile
	.if [bx.ll_count]
	    mov ax,[bx.ll_index]
	    add ax,[bx.ll_celoff]
	    shl ax,2
	    les bx,[bx.ll_list]
	    add bx,ax
	    mov ax,es:[bx]
	    mov dx,es:[bx+2]
	.endif
	ret
getcurobj endp

getcurfile proc
	call getcurobj
	.if !ZERO?
	    add ax,sb_file
	.endif
	ret
getcurfile endp

putcelid proc
	les bx,DLG_FindFile
	mov ah,00h
	mov al,es:[bx.dl_index]
	.if al >= ID_FILE
	    sub ax,ax
	.endif
	inc ax
	mov bx,FCB_FindFile
	add ax,[bx.ll_index]
	mov cx,[bx.ll_count]
	les bx,DLG_FindFile
	mov bx,es:[bx+4]
	add bx,0F04h
	scputf@	bl, bh, 0, 0, offset cstr('[%03d:%03d]'), ax, cx
	ret
putcelid endp

FFAlloc	proc dist pascal path:dword, offs:dword, line:word, ll:word
local	fblk:dword
	push	si
	push	di
	invoke	strlen, path
	add	ax,BLOCKSIZE
	mov	di,ax
	invoke	malloc, ax
	jz	FFAlloc_end
	mov	si,dx
	invoke	memzero, dx::ax, di
	mov	dx,sb_file+4
	invoke	strcpy, es::dx, path
	mov	bx,ll
	push	0
	push	[bx.ll_count]
	call	progress_update
	mov	cx,ax
	mov	bx,ll
	mov	ax,[bx.ll_count]
	inc	[bx.ll_count]
	mov	dx,[bx.ll_count]
	.if dx >= ID_FILE
	    mov dx,ID_FILE
	.endif
	mov	[bx.ll_numcel],dx
	shl	ax,2
	les	bx,[bx.ll_list]
	add	bx,ax
	mov	dx,si
	mov	ax,4
	stom	es:[bx]
	mov	es,dx
	mov	bx,ax
	mov	es:[bx.sb_size],di
	movmw	es:[bx.sb_line],line
	movmx	es:[bx.sb_offs],offs
	mov	ax,bx
	or	cx,cx
	mov	cx,di
	jz	FFAlloc_end
	xor	ax,ax
    FFAlloc_end:
	or	ax,ax
	pop	di
	pop	si
	ret
FFAlloc	endp

ff_fileblock proc dist pascal uses si di directory:dword, wfblk:dword
local \
    path[WMAXPATH]:byte,
    fblk:dword,
    offs:dword,
    line:word,
    fbsize:word,
    ioflag:word,
    iobuf:dword,
    iosize:word,
    result:word
	mov iosize,4096
	stoso iobuf,ds,offset _bufin
	.if func(malloc, 64000)
	    mov iosize,64000
	    stom iobuf
	.endif
      ifdef __386__
	xor eax,eax
	mov offs,eax
      else
	xor ax,ax
	mov word ptr offs,ax
	mov word ptr offs+2,ax
      endif
	mov di,word ptr wfblk
	mov si,word ptr wfblk+2
	mov STDI.ios_l,ax
	mov line,ax
	mov dx,MAXHIT
	mov result,dx
	mov bx,FCB_FindFile
	cmp [bx.ll_count],dx
	jnb ffdofile_end
	mov result,ax
	invoke filter_wblk, si::di
	test ax,ax
	jz ffdofile_end
	add di,wf_name
	invoke strfcat, addr path, directory, si::di
	invoke progress_set, 0, si::di, 1
	mov result,ax
	jnz ffdofile_end
	cmp word ptr directory,ax
	jz ffdofile_fail
	invoke cmpwarg, si::di, fp_maskp
	jz ffdofile_end
	cmp searchstring,0
	je ffdofile_found
	les bx,wfblk
	invoke osopen, addr path, es:[bx.wf_attrib], M_RDONLY, A_OPEN
	mov si,ax
	inc ax
	jz ffdofile_fail
	xor ax,ax
	mov ioflag,ax
	les bx,DLG_FindFile
	.if byte ptr es:[bx+OF_CASE] & _O_FLAGB
	    mov ioflag,IO_SEARCHCASE
	.endif
	.if byte ptr es:[bx+OF_HEXA] & _O_FLAGB
	    or ioflag,IO_SEARCHHEX
	.endif
    ffdofile_search:
	les bx,wfblk
	invoke osearch, si, es:[bx.wf_sizeax], iobuf, iosize, ioflag
	stom offs
	mov line,cx
	inc dx
	jz ffdofile_close
    ffdofile_found:
	invoke FFAlloc, addr path, offs, line, FCB_FindFile
	jz ffdofile_abort
	stom fblk
	mov di,cx
	invoke strlen, ff_basedir
	inc ax
	les bx,fblk
	mov es:[bx],ax
	cmp searchstring,0
	je ffdofile_end
	invoke lseek, si, offs, SEEK_SET
	lodm fblk
	add ax,di
	sub ax,INFOSIZE
	invoke osread, si, dx::ax, INFOSIZE-1
      ifdef __386__
	mov eax,offs
	inc eax
	les bx,wfblk
	cmp eax,es:[bx.wf_sizeax]
	jb @F
	    mov eax,es:[bx.wf_sizeax]
	@@:
	    invoke lseek, si, eax, SEEK_SET
      else
	lodm offs
	les bx,wfblk
	add ax,1
	adc dx,0
	cmprm es:[bx.wf_sizeax]
	jb @F
	    lodm es:[bx.wf_sizeax]
	@@:
	    invoke lseek, si, dx::ax, SEEK_SET
     endif
	    cmp result,0
	    jne ffdofile_close
	    mov bx,FCB_FindFile
	    cmp [bx.ll_count],MAXHIT
	    jb ffdofile_search
    ffdofile_close:
	invoke close, si
    ffdofile_end:
	invoke free, iobuf
	mov ax,result
	ret
    ffdofile_abort:
	invoke close, si
    ffdofile_fail:
	mov result,-1
	jmp ffdofile_end
ff_fileblock endp

ff_directory proc dist pascal directory:dword
	invoke progress_set, 0, directory, 0
	.if ZERO?
	    invoke scan_files, directory
	.endif
	ret
ff_directory endp

ffsearchinitpath proc pascal path:dword
	les si,path
	mov ah,0
	mov dl,' '
	.if es:[si] == dl
	    inc si
	.endif
	.if byte ptr es:[si] == '"'
	    inc si
	    mov dl,'"'
	.endif
	push si
      @@:
	mov al,es:[si]
	test al,al
	jz @F
	inc si
	cmp al,dl
	jne @B
	mov es:[si-1],ah
      @@:
	pop ax
	ret
ffsearchinitpath endp

ffsearchpath proc pascal uses si di directory:dword
local	path[WMAXPATH]:byte
	fpmov fp_fileblock,ff_fileblock
	fpmov fp_directory,ff_directory
	invoke strcpy, addr path, directory
	stom ff_basedir
	.if !path
	    mov ax,'.'
	    mov word ptr path,ax
	.endif
	.repeat
	    invoke ffsearchinitpath, ff_basedir
	    mov word ptr ff_basedir,ax
	    push si
	    .if func(strlen, ff_basedir)
		push ax
		mov bx,word ptr ff_basedir
		dec ax
		add bx,ax
		.if byte ptr es:[bx] == '\'
		    mov byte ptr es:[bx],0
		.endif
		les bx,DLG_FindFile
		mov di,es:[bx+OF_SUBD]
		movmx fp_maskp,es:[bx.to_data+OF_MASK]
		.repeat
		    invoke ffsearchinitpath, fp_maskp
		    mov word ptr fp_maskp,ax
		    push dx
		    .if di & _O_FLAGB
			invoke scan_directory, 1, ff_basedir
		    .else
			invoke ff_directory, ff_basedir
		    .endif
		    pop dx
		    mov word ptr fp_maskp,si
		    les bx,fp_maskp
		    .if dl == '"'
			mov es:[bx-1],dl
		    .endif
		    .break .if !(byte ptr es:[bx])
		    mov es:[bx-1],dl
		.until ax
		pop ax
	    .endif
	    pop si
	    mov word ptr ff_basedir,si
	    .break .if !(byte ptr [si])
	.until !ax
	ret
ffsearchpath endp

event_xcell proc dist
	call putcelid
	les bx,DLG_FindFile
	xor ax,ax
	mov al,es:[bx.dl_index]
	mov bx,FCB_FindFile
	mov [bx.ll_celoff],ax
	call dlxcellevent
	ret
event_xcell endp

event_hexa proc dist
	call dlcheckevent
	cmp ax,KEY_SPACE
	je toggle_hex
	ret
event_hexa endp

event_toggle_format proc dist
	.if ffflag == OUTPUT_LINE
	    mov ffflag,OUTPUT_BINARY
	.elseif ffflag
	    mov ffflag,OUTPUT_LINE
	.else
	    mov ffflag,OUTPUT_TEXT
	.endif
	call event_list
	jmp event_normal
event_toggle_format endp

event_toggle_hex proc dist
	les bx,DLG_FindFile
	cmp es:[bx.dl_index],ID_FILE+2
	jne event_normal
	xor byte ptr es:[bx+OF_HEXA],_O_FLAGB
event_toggle_hex endp

toggle_hex proc dist
	les bx,DLG_FindFile
	pushm es:[bx+OF_SSTR].to_data
	.if byte ptr es:[bx+OF_HEXA] & _O_FLAGB
	    call atohex
	.else
	    call hextoa
	.endif
	call event_list
	jmp event_normal
toggle_hex endp

event_help proc dist
	invoke rsmodal, IDD_FFHelp
	ret
event_help endp

event_edit proc dist
	call getcurfile
	jz event_normal
	push dx
	push ax
	mov es,dx
	mov bx,ax
	push es:[bx-6]
	invoke dlhide, DLG_FindFile
	call tedit
	invoke dlshow, DLG_FindFile
	jmp event_normal
event_edit endp

event_exit proc dist
	call whilekeyalt
	mov ax,_C_ESCAPE
	ret
event_exit endp

event_view proc dist
	les bx,DLG_FindFile
	cmp es:[bx.dl_index],ID_FILE
	jnb event_normal
	call getcurfile
	jz event_normal
	les bx,es:[bx]
	invoke tview, dx::ax, es:[bx.sb_offs], 0, 0
event_view endp

event_normal proc dist
	mov ax,_C_NORMAL
	ret
event_normal endp

ID_INCLUDE	equ	1*16
ID_EXCLUDE	equ	2*16
ID_MIN_DATE	equ	3*16
ID_MAX_DATE	equ	4*16
ID_MIN_SIZE	equ	5*16
ID_MAX_SIZE	equ	6*16
ID_RDONLY	equ	7*16
ID_HIDDEN	equ	8*16
ID_SYSTEM	equ	9*16
ID_VOLID	equ	10*16
ID_SUBDIR	equ	11*16
ID_ARCH		equ	12*16
ID_OK		equ	13*16
ID_CLEAR	equ	14*16
ID_CANCEL	equ	15*16

event_clear PROC DIST
	mov	dx,ds
	mov	cx,si
	lds	si,tdialog
	xor	ax,ax
	mov	bx,[si+ID_MIN_DATE+TO_ODATA]
	mov	[bx],al
	mov	bx,[si+ID_MAX_DATE+TO_ODATA]
	mov	[bx],al
	mov	bx,[si+ID_MIN_SIZE+TO_ODATA]
	mov	[bx],al
	mov	bx,[si+ID_MAX_SIZE+TO_ODATA]
	mov	[bx],al
	mov	ds,dx
	mov	si,cx
	lodm	filter
	push	dx
	mov	bx,ax
	add	ax,of_include
	push	ax
	push	ds
	push	offset cp_stdmask
	invoke	memzero, dx::bx, SIZE S_FILT
	call	strcpy
	les	bx,filter
	mov	es:[bx.of_flag],-1
	mov	dx,word ptr tdialog+2
	mov	ax,ID_RDONLY
	invoke	tosetbitflag, dx::ax, 6, _O_FLAGB, 0FFFFFFFFh
	mov	ax,_C_REOPEN
	ret
event_clear ENDP

filter_edit proc dist pascal public uses si di filt:dword, glcmd:dword
local	DLG_OperationFilters:dword
	xor ax,ax
	mov word ptr filter,ax
	invoke rsopen, IDD_OperationFilters
	jz filter_edit_end
	stom DLG_OperationFilters
	mov di,ax
	lodm filt
	add ax,of_include
	stom es:[di.to_data+ID_INCLUDE]
	mov es:[di.to_count+ID_INCLUDE],8
	add ax,128
	stom es:[di.to_data+ID_EXCLUDE]
	mov es:[di.to_count+ID_EXCLUDE],8
	LPUSH cs
	push offset event_help
	call thelp_set
	mov ax,word ptr glcmd
	stoso es:[di.to_data+ID_OK],ds,ax
	fpmov es:[di.to_proc+ID_CLEAR],event_clear
	mov si,word ptr filt
	.if [si.of_min_date]
	    invoke dwtolstr, es:[di.to_data+ID_MIN_DATE], [si.of_min_date]
	.endif
	.if [si.of_max_date]
	    invoke dwtolstr, es:[di.to_data+ID_MAX_DATE], [si.of_max_date]
	.endif
	lodm [si.of_min_size]
	.if ax
	    push dx
	    push ax
	    mov ax,offset format_lu
	    mov bx,word ptr es:[di.to_data+ID_MIN_SIZE]
	    mov dx,word ptr es:[di.to_data+ID_MIN_SIZE+2]
	    call @sprintf
	    add sp,4
	.endif
	lodm [si.of_max_size]
	.if ax || dx
	    push dx
	    push ax
	    mov ax,offset format_lu
	    mov bx,word ptr es:[di.to_data+ID_MAX_SIZE]
	    mov dx,word ptr es:[di.to_data+ID_MAX_SIZE+2]
	    call @sprintf
	    add sp,4
	.endif
	mov bx,ID_RDONLY+4
	mov ax,[si.of_flag]
	invoke tosetbitflag, es::bx, 6, _O_FLAGB, ax::ax
	invoke dlinit, DLG_OperationFilters
	movmx filter, filt
	invoke rsevent, IDD_OperationFilters, DLG_OperationFilters
	.if ax
	    pushm es:[di].to_data[ID_MIN_DATE]
	    pushm es:[di].to_data[ID_MAX_DATE]
	    pushm es:[di].to_data[ID_MIN_SIZE]
	    pushm es:[di].to_data[ID_MAX_SIZE]
	    push es
	    push ID_RDONLY+4
	    push 6
	    push _O_FLAGB
	    call togetbitflag
	    or ax,0FFC0h
	    mov [si.of_flag],ax
	    call strtol
	    stom [si.of_max_size]
	    call strtol
	    stom [si.of_min_size]
	    call strtodw
	    mov [si.of_max_date],ax
	    call strtodw
	    mov [si.of_min_date],ax
	.else
	    mov word ptr filter,ax
	    mov word ptr filter+2,ax
	.endif
	call thelp_pop
	invoke dlclose, DLG_OperationFilters
	mov ax,_C_NORMAL
    filter_edit_end:
	ret
filter_edit endp

event_filter proc dist
	invoke filter_edit, addr opfilter, 0
	les bx,DLG_FindFile
	mov bx,es:[bx+4]
	add bx,1410h
	sub cx,cx
	mov ax,7
	.if word ptr filter == cx
	    mov al,' '
	.endif
	inc cx
	call @scputw
	jmp event_normal
event_filter endp

event_mklist proc dist
	push si
	push di
	mov si,FCB_FindFile
	sub ax,ax
	.if [si.ll_count] != ax
	    .if func(mklistidd)
		xor di,di
		.while di < [si.ll_count]
		    les bx,[si.ll_list]
		    mov ax,di
		    shl ax,2
		    add bx,ax
		    les bx,es:[bx]
		    mov ax,es:[bx]
		    mov mklist.mkl_offspath,ax
		    movmx mklist.mkl_offset,es:[bx.sb_offs]
		    mov dx,es
		    mov ax,bx
		    add ax,sb_file
		    call mklistadd
		    inc di
		.endw
		invoke close, mklist.mkl_handle
		mov ax,_C_NORMAL
	    .endif
	.endif
	pop di
	pop si
	ret
event_mklist endp

event_list proc dist
	push bp
	push si
	push di
	sub sp,8
	mov bp,sp
	invoke dlinit, DLG_FindFile
	sub ax,ax
	mov al,es:[bx+4]
	mov si,ax
	add si,4
	mov al,es:[bx+5]
	mov di,ax
	add di,2
	mov al,00h
	mov [bp+4],ax
	.repeat
	    mov bx,FCB_FindFile
	    .break .if ax >= [bx.ll_numcel]
	    add ax,[bx.ll_index]
	    shl ax,2
	    les bx,[bx.ll_list]
	    add bx,ax
	    movmx [bp],es:[bx]
	    les bx,[bp]
	    add ax,es:[bx]	; strip search directory from filename
	    mov bx,si
	    mov dx,[bp+4]
	    add dx,di
	    mov bh,dl
	    mov cx,25
	    add ax,sb_file
	    mov dx,[bp+2]
	    call @scpath
	    add al,bl
	    mov ah,bh
	    les bx,[bp]
	    mov bx,es:[bx.sb_line]
	    .if bx
		inc bx	; append (<line>) to filename
		scputf@ al, ah, ch, 7, offset cstr("(%u)"), bx
	    .endif
	    push ds
	    push si
	    push di
	    mov bx,si
	    add bx,33
	    mov ax,di
	    add ax,[bp+4]
	    mov bh,al
	    call @getxyp
	    mov di,bx
	    mov dl,ffflag
	    mov cx,36
	    lds si,[bp]
	    add si,[si.sb_size]
	    sub si,INFOSIZE
	    cld
	    .while cx
		lodsb
		.if dl == OUTPUT_LINE && (al == 10 || al == 13)
		    .break
		.elseif dl && (al == 9 || al == 10 || al == 13)
		    mov ah,al
		    mov al,'\'
		    stosb
		    .if ah == 13
			mov al,'n'
		    .elseif ah == 10
			mov al,'r'
		    .else
			mov al,'t'
		    .endif
		    inc di
		    dec cx
		    .break .if !cx
		.endif
		stosb
		inc di
		dec cx
	    .endw
	    pop di
	    pop si
	    pop ds
	  ifdef __MOUSE__
	    call mouseshow
	  endif
	    mov ax,[bp+4]
	    inc ax
	    mov [bp+4],ax
	.until 0
	mov ax,1
	add sp,8
	pop di
	pop si
	pop bp
	ret
event_list endp

event_find proc dist pascal uses si di
local cursor:dword
	les bx,DLG_FindFile
	invoke getcursor, addr cursor
	call cursoroff
	mov di,FCB_FindFile
	mov si,[di.ll_count]
	mov di,word ptr [di.ll_list]
	.while si
	    mov bx,FCB_FindFile
	    les ax,[bx.ll_list]
	    invoke free, es:[di]
	    add di,4
	    dec si
	.endw
	sub ax,ax
	mov di,FCB_FindFile
	mov [di.ll_celoff],ax
	mov [di.ll_index],ax
	mov [di.ll_numcel],ax
	mov [di.ll_count],ax
	invoke dlinit, DLG_FindFile
	mov ax,es:[bx+4]
	add ax,0F04h
	scputw@ al, ah, 9, 00C4h
	invoke progress_open, addr cp_search, 0
	les bx,DLG_FindFile
      ifdef __386__
	mov eax,es:[bx+OF_PATH].to_data
	push eax
	invoke progress_set, eax, 0, MAXHIT+2
      else
	lodm es:[bx+OF_PATH].to_data
	push dx
	push ax
	invoke progress_set, dx::ax, 0, MAXHIT+2
      endif
	call ffsearchpath
	call progress_close
	invoke setcursor, cursor
	mov ax,[di.ll_count]
	.if ax >= ID_FILE
	    mov ax,ID_FILE
	.endif
	mov [di.ll_numcel],ax
	call update_cellid
	ret
event_find endp

update_cellid proc
	push di
	call putcelid
	call event_list
	les bx,DLG_FindFile
	mov di,FCB_FindFile
	mov cx,ID_FILE
	mov ax,_O_STATE
	.repeat
	    add bx,16
	    or es:[bx],ax
	.untilcxz
	mov bx,word ptr DLG_FindFile
	mov ax,not _O_STATE
	mov cx,[di.ll_numcel]
	.while cx
	    add bx,16
	    and es:[bx],ax
	    dec cx
	.endw
	mov ax,_C_NORMAL
	pop di
	ret
update_cellid endp

event_delete proc dist
	.if func(getcurobj)
	    push dx
	    push ax
	    .repeat
		movmx es:[bx],es:[bx+4]
		add bx,4
	    .until !ax
	    call free
	    mov bx,FCB_FindFile
	    dec [bx.ll_count]
	    mov ax,[bx.ll_count]
	    mov dx,[bx.ll_index]
	    mov cx,[bx.ll_celoff]
	    .if ZERO?
		mov dx,ax
		mov cx,ax
	    .else
		.if dx
		    mov bx,ax
		    sub bx,dx
		    .if bx < ID_FILE
			dec dx
			inc cx
		    .endif
		.endif
		sub ax,dx
		.if ax >= ID_FILE
		    mov ax,ID_FILE
		.endif
		.if cx >= ax
		    dec cx
		.endif
	    .endif
	    mov bx,FCB_FindFile
	    mov [bx.ll_index],dx
	    mov [bx.ll_celoff],cx
	    mov [bx.ll_numcel],ax
	    les bx,DLG_FindFile
	    or ax,ax
	    mov al,cl
	    .if ZERO?
		mov al,ID_FILE
	    .endif
	    mov es:[bx.dl_index],al
	    call update_cellid
	.endif
	mov ax,_C_NORMAL
	ret
event_delete endp

FFOpen proc dist pascal ll:word
	mov ax,ll
	invoke memzero, ss::ax, SIZE S_LOBJ
	mov bx,ll
	mov [bx.ll_dcount],ID_FILE
	fpmov [bx.ll_proc],event_list
	invoke malloc, (MAXHIT*4)+4
	mov bx,ll
	stom [bx.ll_list]
	.if ax
	    invoke memzero, dx::ax, (MAXHIT*4)+4
	    inc ax
	.endif
	ret
FFOpen	endp

FFClose	proc dist pascal uses si di ll:word
	mov si,ll
	mov ax,word ptr [si.ll_list]
	.if ax
	    xor di,di
	    .while di < [si.ll_count]
		les bx,[si.ll_list]
		mov ax,di
		shl ax,2
		add bx,ax
		invoke free, es:[bx]
		inc di
	    .endw
	    invoke free, [si.ll_list]
	    xor ax,ax
	    mov word ptr [si.ll_list],ax
	.endif
	ret
FFClose	endp

FindFile proc dist pascal uses si di wspath:dword
local sbfile:dword, cursor:dword, oldll:word, ll:S_LOBJ
	movmw oldll,FCB_FindFile
	lea ax,ll
	mov FCB_FindFile,ax
	invoke FFOpen, ax
	invoke getcursor, addr cursor
	LPUSH cs
	push offset event_help
	call thelp_set
	xor si,si
	invoke rsopen, IDD_FFFindFile
	jz findfile_somem
	stom DLG_FindFile
	stoso es:[bx.to_data+OF_GCMD],ds,offset GCMD_search
	lodm findfilemask
	stom es:[bx.to_data+OF_MASK]
	les bx,findfilemask
	.if byte ptr es:[bx] == 0
	    invoke strcpy, findfilemask, addr cp_stdmask
	.endif
	les bx,DLG_FindFile
	mov si,offset searchstring
	stoso es:[bx.to_data+OF_SSTR],ds,si
	lodm wspath
	stom es:[bx.to_data+OF_PATH]
	fpmov es:[bx.to_proc+OF_HEXA],event_hexa
	fpmov es:[bx.to_proc+OF_FIND],event_find
	fpmov es:[bx.to_proc+OF_FILT],event_filter
	fpmov es:[bx.to_proc+OF_SAVE],event_mklist
	mov ah,fsflag
	mov al,_O_FLAGB
	.if ah & IO_SEARCHCASE
	    or es:[bx+OF_CASE],al
	.endif
	.if ah & IO_SEARCHHEX
	    or es:[bx+OF_HEXA],al
	.endif
	.if ah & IO_SEARCHSUB
	    or es:[bx+OF_SUBD],al
	.endif
	mov bx,20+TO_OPROC
	mov cx,ID_FILE
	mov ax,offset event_xcell
	LMOV dx,cs
	.repeat
	    mov es:[bx],ax
	    LMOV es:[bx+2],dx
	    add bx,16
	.untilcxz
	invoke dlshow, DLG_FindFile
	invoke dlinit, DLG_FindFile
	mov word ptr filter,0
	mov ax,FCB_FindFile
	stoso tdllist,ds,ax
	.repeat
	    .break .if !func(rsevent, IDD_FFFindFile, DLG_FindFile)
	    mov si,ax
	    mov di,cx
	    mov al,es:[bx.dl_index]
	    .if al < ID_FILE
		call event_view
	    .else
		call event_find
	    .endif
	.until 0
	mov ah,fsflag
	and ah,not (IO_SEARCHCASE or IO_SEARCHSUB or IO_SEARCHHEX)
	mov al,_O_FLAGB
	les bx,DLG_FindFile
	.if es:[bx+OF_CASE] & al
	    or ah,IO_SEARCHCASE
	.endif
	.if es:[bx+OF_HEXA] & al
	    or ah,IO_SEARCHHEX
	.endif
	.if es:[bx+OF_SUBD] & al
	    or ah,IO_SEARCHSUB
	.endif
	mov fsflag,ah
	mov al,es:[bx.dl_index]
	mov ah,00h
	invoke dlclose, DLG_FindFile
	invoke FFClose, FCB_FindFile
    findfile_end:
	movmw FCB_FindFile,oldll
	call thelp_pop
	invoke setcursor, cursor
	mov ax,si		; Exit code
	mov cx,di		; Exit key
	ret
    findfile_somem:
	invoke FFClose, FCB_FindFile
    findfile_nomem:
	mov si,-1
	mov ax,offset CP_ENOMEM
	call @ermsg
	jmp findfile_end
FindFile endp

main	proc dist public
	mov cx,size_info
	mov dx,offset cp_info
	call stderrmsg
	mov bx,word ptr _argv
	invoke strcpy, addr configpath, [bx]
	invoke strfn, dx::ax
	mov bx,ax
	mov byte ptr [bx-1],0
	invoke strfcat, addr configfile, addr configpath, addr ff_cfg
	.if func(osopen, dx::ax, _A_NORMAL, M_RDONLY, A_OPEN) != -1
	    push ax
	    invoke osread, ax, addr tvflag, size_config
	    call close
	.endif
	invoke strfcat, addr configfile, addr configpath, addr ff_ini
	.if func(access, dx::ax, 0)
	    .if func(osopen,addr configfile,_A_NORMAL,M_WRONLY,A_CREATE or A_TRUNC) != -1
		push ax
		mov bx,ax
		or _osfile[bx],FH_TEXT
		invoke write,ax,addr cp_ini,size_ini
		call close
	    .endif
	.endif
      ifdef __MOUSE__
	call mouseinit
	call mouseon
      endif
	invoke FindFile, findfilepath
      ifdef __MOUSE__
	call mouseoff
      endif
	invoke strfcat, addr configfile, addr configpath, addr ff_cfg
	.if func(osopen, dx::ax, _A_NORMAL, M_WRONLY, A_CREATE or A_TRUNC) != -1
	    push ax
	    invoke oswrite, ax, addr tvflag, size_config
	    call close
	.endif
	xor ax,ax
	ret
main	endp

_TEXT	ENDS

	END
