kolibrios-fun/programs/fs/kfar/trunk/filetool.inc

2394 lines
67 KiB
PHP
Raw Normal View History

delete_file_worker:
; in: ecx=flags: 1=deleting directory
; out: eax=0 - OK, eax=1 - retry, eax=2 - skip, eax=-1 - cancel,
; PF, ZF, CF and SF set accordingly to 'cmp eax,2' (or 'cmp al,2')
push ebx
push SF_FILE
pop eax
mov ebx, delinfo
int 0x40
pop ebx
test eax, eax
jz .ret
cmp [del_bSkipAll], 0
jz @f
push 2
pop eax
jmp .ret
@@:
push execdata
push aCannotDeleteFolder
test cl, 1
jnz @f
mov dword [esp], aCannotDeleteFile
@@:
call get_error_msg
push eax
mov eax, esp
push DeleteErrorBtn
push 4
push eax
push 3
call SayErr
add esp, 3*4
cmp al, -1
jz @f
inc eax
cmp al, 4 ; "cancel" button
jnz @f
or eax, -1
@@:
cmp al, 3 ; "skip all" button
jnz .ret
mov [del_bSkipAll], 1
dec eax
.ret:
cmp al, 2
ret
delete_file:
; in: eax->BDFE block
; out: CF and ZF not set <=> cancel job ("ja cancel_label")
pushad
mov [del_dir_stack_ptr], del_dir_stack
lea esi, [ebp + PanelData.dir]
mov edi, execdata
@@:
lodsb
test al, al
jz @f
stosb
jmp @b
@@:
mov esi, [esp+28]
mov ecx, esi
add esi, 40
cmp byte [edi-1], '/'
jz .l1
mov al, '/'
stosb
.l1:
lodsb
cmp edi, execdataend
jb @f
call panels_OnKey.bigfilename
popad
ret
@@:
stosb
test al, al
jnz .l1
mov ecx, [esp+28]
test byte [ecx], 10h
jnz .delete_dir
.retrydel:
xor ecx, ecx
call delete_file_worker
jae @f
jp .retrydel
@@:
popad
ret
.delete_dir:
; recursive delete of directory
xor ebp, ebp ; ebp will contain number of undeletable items
.return_from_recursion:
mov ebx, dirinfo
mov [ebx+dirinfo.first-dirinfo], ebp
mov [ebx+dirinfo.size-dirinfo], del_dir_query_size
mov [ebx+dirinfo.dirdata-dirinfo], del_dir_query_area
mov [ebx+dirinfo.name-dirinfo], execdata
push SF_FILE
pop eax
int 0x40
; if we get read error, the best available action is try to delete directory itself
test eax, eax
jz @f
cmp eax, 6
jnz .do_delete_dir
@@:
; loop through a directory and delete items
mov edx, del_dir_query_area+32
imul ebx, 304
add ebx, edx
.delete_dir_entry_loop:
cmp edx, ebx
jb .do_delete_dir_entry
cmp ebx, del_dir_query_area+32+304*del_dir_query_size
jnz .delete_dir_entry_done
jmp .return_from_recursion
.do_delete_dir_entry:
; ignore special entries "." and ".."
inc ebp
cmp word [edx+40], '.'
jz .delete_dir_entry_continue
cmp word [edx+40], '..'
jnz @f
cmp byte [edx+42], 0
jz .delete_dir_entry_continue
@@:
dec ebp
mov esi, execdata
@@:
lodsb
test al, al
jnz @b
mov byte [esi-1], '/'
mov edi, esi
lea esi, [edx+40]
@@:
cmp edi, execdataend
jae .fullname_big
lodsb
stosb
test al, al
jnz @b
test byte [edx], 10h
jnz .entry_is_folder
.retry2:
xor ecx, ecx
call delete_file_worker
ja .cancel
jz .skip
jp .retry2
jmp .restore_name
.entry_is_folder:
; allocate new item in directory stack
mov eax, [del_dir_stack_ptr]
mov [eax], ebp
add eax, 4
mov [del_dir_stack_ptr], eax
; do recursive deleting
jmp .delete_dir
.fullname_big:
; we will just ignore such files and continue - in real life this situation can not happen
inc ebp
mov esi, execdataend-1
jmp .do_restore_name
.skip:
inc ebp
.restore_name:
mov esi, execdata
@@:
lodsb
test al, al
jnz @b
dec esi
dec esi
.do_restore_name:
call delete_last_name
.delete_dir_entry_continue:
add edx, 304
jmp .delete_dir_entry_loop
.delete_dir_entry_done:
.do_delete_dir:
mov cl, 1
call delete_file_worker
ja .cancel
jz @f
jp .delete_dir
@@:
; al=0 - OK, al=2 - skip this directory
; return to previous directory
; pop item from directory stack
mov ecx, [del_dir_stack_ptr]
cmp ecx, del_dir_stack
jbe .done
sub ecx, 4
mov [del_dir_stack_ptr], ecx
mov ebp, [ecx]
cmp al, 2
sbb ebp, -1
; restore prev directory name
mov esi, execdata
call delete_last_name_from_end
jmp .return_from_recursion
.done:
.cancel:
mov [dirinfo.first], 0 ; do not destroys flags
popad
ret
makedir:
; create directory with name from CopyDestEditBuf+12
; destroys eax
push ebx
push SF_FILE
pop eax
mov ebx, mkdirinfo
int 0x40
pop ebx
test eax, eax
jz .ret
cmp dword [esp+8], DeleteErrorBtn
jnz @f
cmp [copy_bSkipAll], 0
jz @f
push 1
pop eax
jmp .ret
@@:
push dword CopyDestEditBuf+12
push dword aCannotMakeFolder
call get_error_msg
push eax
mov eax, esp
push dword [eax+20]
push dword [eax+16]
push eax
push 3
call SayErr
add esp, 3*4
test eax, eax
jz makedir
.ret:
ret 8
copy_file_worker:
; in: execdata = source name, CopyDestEditBuf+12 = destination name, edx = BDFE block for source
; out: CF and ZF not set <=> cancel job ("ja cancel_label")
; destroys eax,esi,edi
lea edi, [edx+40]
and [source_hFile], 0
copy_file_worker2:
push CopyDestEditBuf+12+513
cmp [bDestIsFolder], 0
jz .noaddtoname
mov esi, CopyDestEditBuf+12
@@:
lodsb
test al, al
jnz @b
pop eax
dec esi
push esi
cmp byte [esi-1], '/'
jz @f
mov byte [esi], '/'
inc esi
@@:
xchg esi, edi
@@:
cmp edi, CopyDestEditBuf+12+513
jae .overflow
lodsb
stosb
test al, al
jnz @b
jmp .noaddtoname
.overflow:
.ret_zf:
pop esi
and byte [esi], 0 ; ZF=1
ret
.noaddtoname:
; <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD> <EFBFBD>!
mov esi, execdata
mov edi, CopyDestEditBuf+12
cmp [source_hModule], 0
jnz @f
push esi edi
call strcmpi
pop edi esi
jnz @f
push esi
push aCannotCopyToSelf
mov eax, esp
push ContinueBtn
push 1
push eax
push 2
call SayErr
pop eax
pop eax
jmp .ret_zf
@@:
; <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
; esi->source name, edi->destination name
push ebx
mov [writeinfo.code], 2
mov [writeinfo.name], edi
and dword [writeinfo.first], 0
and dword [writeinfo.first+4], 0
mov [writeinfo.data], copy_buffer
mov ebx, readinfo
and dword [ebx+readinfo.first-readinfo], 0
and dword [ebx+readinfo.first+4-readinfo], 0
mov [ebx+readinfo.size-readinfo], copy_buffer_size
mov [ebx+readinfo.data-readinfo], copy_buffer
mov [ebx+readinfo.name-readinfo], esi
mov eax, [source_hFile]
push eax
test eax, eax
jnz .copyloop
.source_reopen:
mov eax, [source_hModule]
test eax, eax
jz .copyloop
pushad
push O_READ+O_SEQUENTIAL_ONLY
push esi
push [source_hPlugin]
call [eax+PluginInfo.open]
mov [source_hFile], eax
popad
.copyloop:
mov ebx, readinfo
mov eax, [source_hModule]
test eax, eax
jz .native
mov ecx, [source_hFile]
jecxz .readerr
pushad
push [ebx+readinfo.size-readinfo]
push [ebx+readinfo.data-readinfo]
push ecx
call [eax+PluginInfo.read]
mov [esp+28], eax
popad
cmp eax, -1
jz .readerr
mov ebx, eax
jmp .copyreadok
.native:
push SF_FILE
pop eax
int 0x40
test eax, eax
jz .copyreadok
cmp eax, 6
jz .copyreadok
.readerr:
cmp [copy_bSkipAll2], 0
jnz .copyfailed_del2
push esi
push dword aCannotReadFile
call get_error_msg
push eax
mov eax, esp
push dword DeleteErrorBtn
push 4
push eax
push 3
call SayErr
add esp, 3*4
test eax, eax
jnz .copyfailed_parseuser
cmp [source_hModule], 0
jz .copyloop
cmp [source_hFile], 0
jz .source_reopen
jmp .copyloop
.copyreadok:
add dword [readinfo.first], ebx
adc dword [readinfo.first+4], 0
mov [writeinfo.size], ebx
test ebx, ebx
jnz .copywrite
cmp byte [writeinfo.code], 2
jnz .copydone
.copywrite:
mov ebx, writeinfo
push SF_FILE
pop eax
int 0x40
test eax, eax
jz .copywriteok
cmp [copy_bSkipAll2], 0
jnz .copyfailed_del2
push edi
push dword aCannotWriteFile
call get_error_msg
push eax
mov eax, esp
push dword DeleteErrorBtn
push 4
push eax
push 3
call SayErr
add esp, 3*4
test eax, eax
jz .copywrite
.copyfailed_parseuser:
cmp al, 2
jnz @f
mov [copy_bSkipAll2], 1
dec eax
@@:
cmp al, 1
pushf
jmp .copyfailed
.copywriteok:
mov ecx, [writeinfo.size]
add dword [writeinfo.first], ecx
adc dword [writeinfo.first+4], 0
mov [writeinfo.code], 3
cmp ecx, copy_buffer_size
jz .copyloop
.copydone:
pop ecx
test ecx, ecx
jnz @f
mov eax, [source_hModule]
test eax, eax
jz @f
mov ecx, [source_hFile]
jecxz @f
push edx
push ecx
call [eax+PluginInfo.close]
pop edx
@@:
; now try to set attributes from source, ignore errors
mov edi, attrinfo.attr
mov esi, edx
push 8
pop ecx
rep movsd
; replace zero dates with default values
mov eax, [default_attr]
cmp dword [edi-32+8], 0
jnz @f
mov ecx, [eax+8]
mov [edi-32+8], ecx
mov ecx, [eax+12]
mov [edi-32+12], ecx
@@:
cmp dword [edi-32+16], 0
jnz @f
mov ecx, [eax+16]
mov [edi-32+16], ecx
mov ecx, [eax+20]
mov [edi-32+20], ecx
@@:
cmp dword [edi-32+24], 0
jnz @f
mov ecx, [eax+24]
mov [edi-32+24], ecx
mov ecx, [eax+28]
mov [edi-32+28], ecx
@@:
mov ebx, attrinfo
mov [ebx+attrinfo.name-attrinfo], CopyDestEditBuf+12
inc dword [ebx]
push SF_FILE
pop eax
push ebx
int 0x40
pop ebx
dec dword [ebx]
xor eax, eax ; ZF=1
.ret:
pop ebx
pop esi
mov byte [esi], 0
ret
.copydone2:
popf
jmp .ret
.copyfailed:
pop eax
pop ecx
push eax
test ecx, ecx
jnz @f
mov eax, [source_hModule]
test eax, eax
jz @f
mov ecx, [source_hFile]
jecxz @f
push ecx
call [eax+PluginInfo.close]
@@:
cmp [bConfirmDeleteIncomplete], 0
jz .copyfailed_del
cmp [writeinfo.code], 2
jz .copydone2
push dword aIncompleteFile
mov eax, esp
push dword DeleteOrKeepBtn
push 2
push eax
push 1
push dword aCopyCaption
call Message
add esp, 4
test eax, eax
jnz .copydone2
.copyfailed_del:
mov ebx, delinfo
push dword [ebx+21]
mov dword [ebx+21], edi
push SF_FILE
pop eax
int 0x40
; ignore errors
pop dword [delinfo+21]
jmp .copydone2
.copyfailed_del2:
xor eax, eax
pushf
jmp .copyfailed_del
copy_file:
; in: eax->BDFE block for source, CopyDestEditBuf+12 contains ASCIIZ full name for destination
; out: CF and ZF not set <=> cancel job ("ja cancel_label")
pushad
mov [copy_dir_stack_ptr], copy_dir_stack
mov [bNeedRestoreName], 0
lea esi, [ebp + PanelData.dir]
mov edi, execdata
@@:
lodsb
test al, al
jz @f
stosb
jmp @b
@@:
mov esi, [esp+28]
add esi, 40
cmp byte [edi-1], '/'
jz .l1
mov al, '/'
stosb
.l1:
lodsb
cmp edi, execdataend
jb @f
call panels_OnKey.bigfilename
stc
popad
ret
@@:
stosb
test al, al
jnz .l1
mov edx, [esp+28]
test byte [edx], 10h
jnz .copy_dir
call copy_file_worker
.popad_ret:
popad
ret
.biiig:
mov byte [edi-1], 0
jmp .popad_ret
.copy_dir:
; recursive copy of directory
cmp [bDestIsFolder], 0
mov [bDestIsFolder], 0
jz .target_created
mov [bNeedRestoreName], 1
mov esi, CopyDestEditBuf+12
@@:
lodsb
test al, al
jnz @b
dec esi
cmp byte [esi-1], '/'
jz @f
mov byte [esi], '/'
inc esi
@@:
mov edi, esi
lea esi, [edx+40]
@@:
cmp edi, CopyDestEditBuf+12+513
jae .biiig
lodsb
stosb
test al, al
jnz @b
.create_target:
.enter_recursion:
push DeleteErrorBtn
push 4
call makedir
jz .target_created
cmp al, 2
jnz @f
dec eax
mov [copy_bSkipAll], 1
@@:
cmp al, 1
jz .copy_dir_entry_done
jmp .cancel2
.target_created:
mov edx, [source_hModule]
test edx, edx
jz .nosetdir
mov esi, execdata
push esi ; absolute_path
@@:
lodsb
test al, al
jnz @b
@@:
dec esi
cmp byte [esi-1], '/'
jnz @b
push esi ; relative_path
push [source_hPlugin] ; hPlugin
call [edx+PluginInfo.SetFolder]
test al, al
jnz .nosetdir
cmp [copy_bSkipAll3], 0
jz .skip2
push execdata
push aCannotSetFolder
mov eax, esp
push DeleteErrorBtn
push 4
push eax
push 2
call SayErr
pop ecx ecx
test al, al
jz .target_created
cmp al, 2
setz [copy_bSkipAll3]
ja .cancel2
jmp .skip2
.nosetdir:
xor ebp, ebp ; ebp will contain number of copied items
.return_from_recursion:
.read_retry:
mov ebx, dirinfo
mov [ebx+dirinfo.first-dirinfo], ebp
mov [ebx+dirinfo.size-dirinfo], copy_dir_query_size
mov [ebx+dirinfo.dirdata-dirinfo], copy_dir_query_area
mov [ebx+dirinfo.name-dirinfo], execdata
mov eax, [source_hModule]
test eax, eax
jz .readfolder_native
push ebp
push [ebx+dirinfo.dirdata-dirinfo]
push [ebx+dirinfo.size-dirinfo]
push [ebx+dirinfo.first-dirinfo]
push [source_hPlugin]
call [eax+PluginInfo.ReadFolder]
pop ebp
mov ebx, dword [copy_dir_query_area+4]
jmp @f
.readfolder_native:
push SF_FILE
pop eax
int 0x40
@@:
test eax, eax
jz .readok
cmp eax, 6
jz .readok
; read error
cmp [copy_bSkipAll], 0
jnz .skip1
mov edx, execdata
call recursive_read_folder_err
jz .read_retry
cmp al, 2
jnz @f
dec eax
mov [copy_bSkipAll], 1
@@:
cmp al, 1
jz .skip1
jmp .cancel
.readok:
; loop through a directory and copy items
mov edx, copy_dir_query_area+32
imul ebx, 304
add ebx, edx
.copy_dir_entry_loop:
cmp edx, ebx
jb .do_copy_dir_entry
cmp ebx, copy_dir_query_area+32+copy_dir_query_size*304
jz .return_from_recursion
jmp .copy_dir_entry_done
.do_copy_dir_entry:
inc ebp
; ignore special entries "." and ".."
cmp word [edx+40], '.'
jz .copy_dir_entry_continue
cmp word [edx+40], '..'
jnz @f
cmp byte [edx+42], 0
jz .copy_dir_entry_continue
@@:
mov esi, execdata
@@:
lodsb
test al, al
jnz @b
dec esi
cmp byte [esi-1], '/'
jz @f
mov byte [esi], '/'
inc esi
@@:
mov edi, esi
lea esi, [edx+40]
@@:
cmp edi, execdataend
jae .fullname_big
lodsb
stosb
test al, al
jnz @b
mov esi, CopyDestEditBuf+12
@@:
lodsb
test al, al
jnz @b
dec esi
cmp byte [esi-1], '/'
jz @f
mov byte [esi], '/'
inc esi
@@:
mov edi, esi
lea esi, [edx+40]
@@:
cmp edi, CopyDestEditBuf+513
jae .fullname2_big
lodsb
stosb
test al, al
jnz @b
test byte [edx], 10h
jnz .entry_is_folder
call copy_file_worker
ja .cancel3
jmp .restore_name
.entry_is_folder:
; allocate new item in directory stack
mov eax, [copy_dir_stack_ptr]
mov [eax], ebp
add eax, 4
mov [copy_dir_stack_ptr], eax
; do recursive copying
jmp .enter_recursion
.fullname_big:
; we will just ignore such files and continue - in real life this situation can not happen
mov esi, execdataend-1
jmp .do_restore_name2
.fullname2_big:
mov esi, CopyDestEditBuf+12+512
jmp .restore_name2
.restore_name:
mov esi, CopyDestEditBuf+12
@@:
lodsb
test al, al
jnz @b
dec esi
dec esi
.restore_name2:
call delete_last_name
mov esi, execdata
@@:
lodsb
test al, al
jnz @b
dec esi
dec esi
.do_restore_name2:
call delete_last_name
.copy_dir_entry_continue:
add edx, 304
jmp .copy_dir_entry_loop
.skip1:
.copy_dir_entry_done:
; return to previous directory
mov esi, execdata
call delete_last_name_from_end
mov eax, [source_hModule]
test eax, eax
jz @f
push execdata
push aDotDot
push [source_hPlugin]
call [eax+PluginInfo.SetFolder]
jmp @f
.skip2:
mov esi, execdata
call delete_last_name_from_end
@@:
; pop item from directory stack
mov ecx, [copy_dir_stack_ptr]
cmp ecx, copy_dir_stack
jbe .done
sub ecx, 4
mov [copy_dir_stack_ptr], ecx
mov ebp, [ecx]
; restore prev directory name
mov esi, CopyDestEditBuf+12
call delete_last_name_from_end
jmp .return_from_recursion
.done:
mov [dirinfo.first], 0 ; do not destroys flags
popad
ret
.cancel2:
sub [copy_dir_stack_ptr], 4
.cancel3:
mov esi, execdata
call delete_last_name_from_end
.cancel:
mov eax, [source_hModule]
test eax, eax
jz .cancel.ret
cmp [copy_dir_stack_ptr], copy_dir_stack
jb .cancel.ret
push execdata
push aDotDot
push [source_hPlugin]
call [eax+PluginInfo.SetFolder]
jmp .cancel2
.cancel.ret:
xor eax, eax
inc eax
jmp .done
delete_last_name_from_end:
lodsb
test al, al
jnz delete_last_name_from_end
dec esi
dec esi
delete_last_name:
std
@@:
lodsb
cmp al, '/'
jnz @b
cld
inc esi
cmp esi, execdata
jz @f
cmp esi, CopyDestEditBuf+12
jz @f
dec esi
@@:
mov byte [esi+1], 0
ret
recursive_read_folder_err:
push edx
push aCannotReadFolder
call get_error_msg
push eax
mov eax, esp
push DeleteErrorBtn
push 4
push eax
push 3
call SayErr
add esp, 3*4
test al, al
ret
recursive_read_file_err:
push edx
push aCannotReadFile
call get_error_msg
push eax
mov eax, esp
push DeleteErrorBtn
push 4
push eax
push 3
call SayErr
add esp, 3*4
test al, al
ret
copy_AddDir:
push 1
pop eax ; for "return true"
pushad
mov esi, CopyDestEditBuf+12
@@:
lodsb
test al, al
jnz @b
cmp byte [esi-2], '/'
jnz @f
dec esi
@@:
push dword [esi-1]
push esi
mov byte [esi-1], '/'
mov edi, esi
mov esi, [esp+28h+4]
.0:
lodsb
stosb
cmp edi, CopyDestEditBuf+12+512
jae .done
test al, al
jnz .0
push RetryOrCancelBtn
push 2
call makedir
jz .done
and dword [esp+8+1Ch], 0
.done:
pop esi
pop dword [esi-1]
popad
ret 8
copy_AddFile:
pushad
mov eax, [esp+20h+12]
mov [source_hFile], eax
mov edx, [esp+20h+8]
mov edi, [esp+20h+4]
call copy_file_worker2
popad
setna al
ret 12
search_dir_query_size = 32
search_filebuf_size = 32768
virtual at 0
filesearch_data:
.prev_screen_vtable dd ? ; previous in window stack
.prev_screen_data dd ?
.tid dd ? ; -1 for query stage, secondary thread id for search stage
.slot dd ? ; 0 if secondary thread is not running, it's slot otherwise
.result_blocks dd ? ; head of heap blocks for resulting data
.cur_result_ptr dd ? ; offset of free data in the current heap block for result
.stop db ? ; set to 1 when secondary thread need to be stopped
.skip_errors_mask db ?
.skip_read_folder = 1
.skip_set_folder = 2
.skip_open_file = 4
.skip_read_file = 8
.skip_bigname = 10h
.updating db ?
.datachanged db ?
.list.curitemptr dd ?
.list.numitems dd ?
.list.head dd ?
.list.curitem dd ?
.list.end dd ?
.query_dlgdata rb sizeof.FileSearch_QueryTemplate
.search_dlgdata rb sizeof.FileSearch_SearchTemplate
.mask.maxlen dd ?
.mask.pos dd ?
.mask.start dd ?
.mask rb 512
.string.maxlen dd ?
.string.pos dd ?
.string.start dd ?
.string rb 256
.caption rb 268
.statusstr rb 80
.stack rb 8192
.stacktop = $
.fs.func dd ?
.fs.pos_low dd ?
.fs.pos_high dd ?
.fs.size dd ?
.fs.ptr dd ?
.curfile rb 1024
.curdir rb 1024
.lowername rb 264
.dir_area rb 32 + 304*search_dir_query_size
.filebuf rb search_filebuf_size
.size = $
end virtual
panels_OnKey.alt_f7:
mov ecx, filesearch_data.size
mov edx, filesearch_vtable
call new_screen
test eax, eax
jnz @f
ret
@@:
mov [ebp+filesearch_data.prev_screen_vtable], panels_vtable
mov ecx, (sizeof.FileSearch_QueryTemplate + sizeof.FileSearch_SearchTemplate) / 4
mov esi, filesearch_query_template
lea edi, [ebp+filesearch_data.query_dlgdata]
rep movsd
lea eax, [ebp+filesearch_data.string.maxlen]
xor ebx, ebx
mov dword [ebp+filesearch_data.query_dlgdata+FileSearch_QueryTemplate.edit2.text], eax
mov dword [eax], 253
mov [eax+4], ebx
mov [eax+8], ebx
mov [eax+12], bl
sub eax, filesearch_data.string - filesearch_data.mask
mov dword [ebp+filesearch_data.query_dlgdata+FileSearch_QueryTemplate.edit1.text], eax
mov dword [eax], 511
mov [eax+8], ebx
inc ebx
mov word [eax+12], '*'
mov [eax+4], ebx
mov eax, [find_in_file_dlgdata.case.flags]
and al, 10h
or al, 8
mov dword [ebp+filesearch_data.query_dlgdata+FileSearch_QueryTemplate.case.flags], eax
mov eax, [find_in_file_dlgdata.whole.flags]
and al, 10h
or al, 8
mov dword [ebp+filesearch_data.query_dlgdata+FileSearch_QueryTemplate.whole.flags], eax
lea edi, [ebp+filesearch_data.caption]
mov dword [ebp+dlgtemplate.title+filesearch_data.search_dlgdata], edi
lea eax, [ebp+filesearch_data.list.curitemptr]
mov dword [ebp+filesearch_data.search_dlgdata+FileSearch_SearchTemplate.list1.text], eax
.reinit:
xor ebx, ebx
or [ebp+filesearch_data.tid], -1
mov [ebp+filesearch_data.slot], ebx
mov [ebp+filesearch_data.result_blocks], ebx
mov [ebp+filesearch_data.cur_result_ptr], 0x4000
mov [ebp+filesearch_data.list.curitemptr], ebx
mov [ebp+filesearch_data.list.numitems], ebx
mov [ebp+filesearch_data.list.head], ebx
mov [ebp+filesearch_data.list.curitem], ebx
mov [ebp+filesearch_data.list.end], ebx
mov [ebp+filesearch_data.stop], bl
mov al, [dialog_main_color]
mov [ebp+filesearch_data.query_dlgdata+dlgtemplate.main_color], al
mov [ebp+filesearch_data.search_dlgdata+dlgtemplate.main_color], al
mov al, [dialog_border_color]
mov [ebp+filesearch_data.query_dlgdata+dlgtemplate.border_color], al
mov [ebp+filesearch_data.search_dlgdata+dlgtemplate.border_color], al
mov al, [dialog_header_color]
mov [ebp+filesearch_data.query_dlgdata+dlgtemplate.header_color], al
mov [ebp+filesearch_data.search_dlgdata+dlgtemplate.header_color], al
filesearch_OnRedraw:
push ebp
mov byte [draw_image], 0xC3
mov eax, [ebp+filesearch_data.prev_screen_vtable]
mov ebp, [ebp+filesearch_data.prev_screen_data]
call dword [eax+screen_vtable.OnRedraw]
mov byte [draw_image], 0xC6
pop ebp
cmp [ebp+filesearch_data.tid], -1
jnz .prepare_search_dlg
lea ebx, [ebp+filesearch_data.query_dlgdata]
mov eax, [cur_width]
mov [ebx + dlgtemplate.x], 6
sub eax, 12
mov [ebx + dlgtemplate.width], eax
dec eax
dec eax
mov [ebx + FileSearch_QueryTemplate.edit1.x2], eax
mov [ebx + FileSearch_QueryTemplate.edit2.x2], eax
shr eax, 1
dec eax
dec eax
mov [ebx + FileSearch_QueryTemplate.search.x2], eax
sub eax, aSearchBLength-1
mov [ebx + FileSearch_QueryTemplate.search.x1], eax
add eax, aSearchBLength+3
mov [ebx + FileSearch_QueryTemplate.cnl.x1], eax
add eax, aCancelBLength-1
mov [ebx + FileSearch_QueryTemplate.cnl.x2], eax
mov eax, [cur_height]
sub eax, [ebx + dlgtemplate.height]
shr eax, 1
mov [ebx + dlgtemplate.y], eax
jmp .dlg_prepared
.prepare_search_dlg:
lea ebx, [ebp+filesearch_data.search_dlgdata]
; width: for big screens use all screen except for one column on each side,
; that is, [cur_width] - 10 (standard frame width is 4);
; if [cur_width]-10 does not contain enough place for all buttons with two spaces between them,
; but [cur_width]-2 does, use fixed size = place for all buttons with two spaces between them
; for small screens use [cur_width]-2 as maximum possible
.btnsize = 2 + aNewSearchLen + 2 + aGotoLen + 2 + aViewLen + 2 + aCancelB2Length + 2
mov eax, [cur_width]
mov edx, eax
sub eax, 10
cmp eax, .btnsize
jae @f
add eax, 8
cmp eax, .btnsize
jb @f
mov al, .btnsize
@@:
mov [ebx + dlgtemplate.width], eax
sub edx, eax
shr edx, 1
mov [ebx + dlgtemplate.x], edx
dec eax
mov [ebx + FileSearch_SearchTemplate.list1.x2], eax
mov [ebx + FileSearch_SearchTemplate.lbl2.x2], eax
cmp [ebp + filesearch_data.slot], 0
jnz @f
mov [ebx + FileSearch_SearchTemplate.lbl1.x2], eax
@@:
sub eax, aNewSearchLen + aGotoLen + aViewLen + aCancelB2Length - 1
cdq
push 5
pop ecx
idiv ecx
sar edx, 1
add edx, eax
inc eax
mov [ebx + FileSearch_SearchTemplate.btn1.x1], edx
add edx, aNewSearchLen-1
mov [ebx + FileSearch_SearchTemplate.btn1.x2], edx
add edx, eax
mov [ebx + FileSearch_SearchTemplate.btn2.x1], edx
add edx, aGotoLen-1
mov [ebx + FileSearch_SearchTemplate.btn2.x2], edx
add edx, eax
mov [ebx + FileSearch_SearchTemplate.btn3.x1], edx
add edx, aViewLen-1
mov [ebx + FileSearch_SearchTemplate.btn3.x2], edx
add edx, eax
mov [ebx + FileSearch_SearchTemplate.btn4.x1], edx
add edx, aCancelB2Length-1
mov [ebx + FileSearch_SearchTemplate.btn4.x2], edx
mov eax, [cur_height]
mov edx, eax
sub eax, 8
cmp eax, 6
jae @f
mov eax, 6
@@:
mov [ebx + dlgtemplate.height], eax
sub edx, eax
shr edx, 1
mov [ebx + dlgtemplate.y], edx
dec eax
mov [ebx + FileSearch_SearchTemplate.btn1.y1], eax
mov [ebx + FileSearch_SearchTemplate.btn2.y1], eax
mov [ebx + FileSearch_SearchTemplate.btn3.y1], eax
mov [ebx + FileSearch_SearchTemplate.btn4.y1], eax
dec eax
mov [ebx + FileSearch_SearchTemplate.lin2.y1], eax
dec eax
mov [ebx + FileSearch_SearchTemplate.lbl1.y1], eax
mov [ebx + FileSearch_SearchTemplate.lbl2.y1], eax
dec eax
mov [ebx + FileSearch_SearchTemplate.lin1.y1], eax
dec eax
mov [ebx + FileSearch_SearchTemplate.list1.y2], eax
.dlg_prepared:
call draw_dialog_shadow
push ebx
call DrawDialogBox
ret
filesearch_OnActivate:
mov eax, [active_screen_data]
cmp eax, ebp
jz @f
mov [ebp+filesearch_data.prev_screen_data], eax
mov eax, [active_screen_vtable]
mov [ebp+filesearch_data.prev_screen_vtable], eax
@@:
mov eax, [ebp+filesearch_data.prev_screen_data]
mov ecx, [num_screens]
mov edx, [screens]
push edx
@@:
cmp [edx+4], eax
jz @f
add edx, 8
loop @b
@@:
pop edx
jz @f
mov eax, [active_screen]
dec eax
mov ecx, [edx+eax*8+4]
mov [ebp+filesearch_data.prev_screen_data], ecx
mov ecx, [edx+eax*8]
mov [ebp+filesearch_data.prev_screen_vtable], ecx
@@:
cmp [ebp+filesearch_data.slot], 0
jz @f
mov [idle_interval], 10
@@:
; ret ; continue to filesearch_OnIdle
filesearch_OnIdle:
xor eax, eax
xchg al, [ebp+filesearch_data.datachanged]
cmp al, 1
ja .done
jz .new
.ret:
ret
.done:
call filesearch_wait_thread
call filesearch_done
.new:
jmp filesearch_OnRedraw
filesearch_OnKey:
cmp al, 0x58
jz F12
cmp [ebp+filesearch_data.tid], -1
jz .handle_generic
cmp al, 0x47
jb .notforlist
cmp al, 0x49
jbe @f
cmp al, 0x4F
jb .notforlist
cmp al, 0x51
ja .notforlist
@@:
push ebp
add ebp, filesearch_data.search_dlgdata
lea ebx, [ebp+dlgtemplate.size+12]
call listbox_key
call draw_listbox
call draw_image
pop ebp
ret
.notforlist:
cmp al, 0x3D
jz .view
.handle_generic:
push ebp
call filesearch_getcurdlg
push 0
push eax
push 2
push ebx
call ManagerDlgProc
pop ebp
test eax, eax
jz filesearch_OnIdle.ret
cmp eax, -1
jz .esc
sub eax, ebp
cmp eax, filesearch_data.query_dlgdata+FileSearch_QueryTemplate.search
jz .query
cmp eax, filesearch_data.search_dlgdata+FileSearch_SearchTemplate.btn1
jz .newsearch
cmp eax, filesearch_data.search_dlgdata+FileSearch_SearchTemplate.btn2
jz .goto
cmp eax, filesearch_data.search_dlgdata+FileSearch_SearchTemplate.btn3
jz .view
.esc:
cmp dword [ebp+filesearch_data.slot], 0
jz .exit
mov [ebp+filesearch_data.stop], 2
call ConfirmCancel
setz [ebp+filesearch_data.stop]
.ret:
ret
.exit:
call filesearch_OnExit
jmp delete_active_screen
.view:
mov esi, [ebp+filesearch_data.list.curitemptr]
test esi, esi
jz .ret
add esi, 8
mov eax, esi
jmp view_file
.goto:
mov esi, [ebp+filesearch_data.list.curitemptr]
test esi, esi
jz .ret
add esi, 8
cmp byte [esi], '/'
jnz .ret
cmp byte [esi+1], 0
jz .ret
push ebp
mov ebp, [active_panel]
push esi
call close_plugin_panels
pop esi
mov ecx, esi
@@:
lodsb
test al, al
jnz @b
@@:
dec esi
cmp byte [esi], '/'
jnz @b
mov byte [esi], 0
inc esi
mov edi, saved_file_name
@@:
lodsb
stosb
test al, al
jnz @b
mov esi, ecx
lea edi, [ebp + PanelData.dir]
push esi edi
call strcmpi
pop edi esi
jz .goto.samedir
@@:
lodsb
stosb
test al, al
jnz @b
and [ebp + PanelData.start], 0
and [ebp + PanelData.index], 0
.goto.samedir:
push @f
push [ebp + PanelData.index]
jmp panels_OnKey.ctrl_r.doread
@@:
pop ebp
jmp .exit
.newsearch:
cmp [ebp+filesearch_data.slot], 0
jz .do.newsearch
call filesearch_stop_thread
.do.newsearch:
call filesearch_free_result
jmp panels_OnKey.alt_f7.reinit
.query:
mov esi, [active_panel]
cmp [esi + PanelData.hPlugin], 0
jz @f
push aCannotSearchOnPlugin
mov eax, esp
push ContinueBtn
push 1
push eax
push 1
call SayErr
pop eax
jmp .exit
@@:
add esi, PanelData.dir
lea edi, [ebp+filesearch_data.curdir]
@@:
lodsb
stosb
test al, al
jnz @b
push SF_CREATE_THREAD
pop eax
push 1
pop ebx
mov ecx, filesearch_thread
lea edx, [ebp+filesearch_data.stacktop-4]
mov [edx], ebp
int 40h
cmp eax, -1
jnz @f
push ContinueBtn
push 1
push aCannotCreateThread_ptr
push 1
call SayErr
ret
@@:
mov [ebp+filesearch_data.tid], eax
mov [ebp+filesearch_data.updating], 0
mov [ebp+filesearch_data.datachanged], 0
xchg eax, ecx
push SF_SYSTEM
pop eax
push SSF_GET_THREAD_SLOT
pop ebx
int 40h
mov [ebp+filesearch_data.slot], eax
mov [idle_interval], 10
mov esi, aFileSearch
mov edi, dword [ebp+filesearch_data.search_dlgdata+dlgtemplate.title]
@@:
lodsb
stosb
test al, al
jnz @b
mov byte [edi-1], ':'
mov al, ' '
stosb
lea esi, [ebp+filesearch_data.mask]
@@:
lodsb
stosb
test al, al
jnz @b
lea edi, [ebp+filesearch_data.statusstr]
mov dword [ebp+filesearch_data.search_dlgdata+FileSearch_SearchTemplate.lbl1.text], edi
mov esi, aSearchingIn
@@:
lodsb
stosb
cmp al, '"'
jnz @b
push esi
push 10
pop ecx
lea esi, [ebp+filesearch_data.string]
@@:
lodsb
test al, al
jz @f
stosb
loop @b
@@:
pop esi
movsb
jz @f
mov byte [edi-1], '.'
mov byte [edi-2], '.'
mov byte [edi-3], '.'
mov byte [edi-4], '"'
@@:
cmp byte [edi-2], '"'
jnz @f
sub edi, 3
@@:
lodsb
stosb
test al, al
jnz @b
sub edi, dword [ebp +filesearch_data.search_dlgdata +FileSearch_SearchTemplate.lbl1.text]
mov dword [ebp+filesearch_data.search_dlgdata+FileSearch_SearchTemplate.lbl1.x2], edi
inc edi
mov dword [ebp+filesearch_data.search_dlgdata+FileSearch_SearchTemplate.lbl2.x1], edi
lea eax, [ebp+filesearch_data.curdir]
mov dword [ebp+filesearch_data.search_dlgdata+FileSearch_SearchTemplate.lbl2.text], eax
call filesearch_set_dlgflags ; use it? I think, yes
cmp [ebp+filesearch_data.slot], 0
jnz @f
call filesearch_done
@@:
jmp filesearch_OnRedraw
filesearch_done:
cmp [active_screen_data], ebp
jnz @f
or [idle_interval], -1
@@:
and dword [ebp+filesearch_data.search_dlgdata+FileSearch_SearchTemplate.lbl2.text], 0
mov edi, dword [ebp+filesearch_data.search_dlgdata+FileSearch_SearchTemplate.lbl1.text]
mov esi, aSearchDone
@@:
lodsb
stosb
cmp al, '?'
jnz @b
dec edi
mov eax, [ebp+filesearch_data.list.numitems]
push -'0'
push 10
pop ecx
@@:
xor edx, edx
div ecx
push edx
test eax, eax
jnz @b
@@:
pop eax
add al, '0'
jz @f
stosb
jmp @b
@@:
lodsb
stosb
test al, al
jnz @b
ret
filesearch_getname:
if lang eq ru
mov eax, '<27><><EFBFBD><EFBFBD>'
stosd
mov eax, '<27><> <20>'
stosd
mov eax, '<27><><EFBFBD><EFBFBD>'
stosd
mov al, '<27>'
stosb
else
mov eax, 'Find'
stosd
mov eax, ' dia'
stosd
mov eax, 'log '
stosd
mov al, ' '
stosb
end if
ret
filesearch_stop_thread:
mov [ebp+filesearch_data.stop], 1
filesearch_wait_thread:
mov ecx, [ebp+filesearch_data.slot]
mov edx, [ebp+filesearch_data.tid]
jecxz .secondary_thread_exited
@@:
mov ebx, procinfo
push SF_THREAD_INFO
pop eax
int 40h
cmp word [ebx+50], 9
jz .secondary_thread_exited
cmp dword [ebx+30], edx
jnz .secondary_thread_exited
push SF_SLEEP
pop eax
push 1
pop ebx
int 40h
jmp @b
.secondary_thread_exited:
and [ebp+filesearch_data.slot], 0
ret
filesearch_OnExit:
call filesearch_stop_thread
call filesearch_free_result
; call filesearch_set_dlgflags ; use it? I think, no
ret
filesearch_IsHandleUsed:
test ebp, ebp
ret
filesearch_set_dlgflags:
mov eax, dword [ebp+filesearch_data.query_dlgdata+FileSearch_QueryTemplate.case.flags]
and al, 10h
or al, 8
mov [find_in_file_dlgdata.case.flags], eax
mov eax, dword [ebp+filesearch_data.query_dlgdata+FileSearch_QueryTemplate.whole.flags]
and al, 10h
or al, 8
mov [find_in_file_dlgdata.whole.flags], eax
lea esi, [ebp+filesearch_data.string]
mov edi, SearchString
and dword [edi-4], 0
and dword [edi-8], 0
@@:
lodsb
stosb
test al, al
jnz @b
ret
filesearch_getcurdlg:
lea ebx, [ebp+filesearch_data.query_dlgdata]
cmp [ebp+filesearch_data.tid], -1
jz @f
add ebx, filesearch_data.search_dlgdata - filesearch_data.query_dlgdata
@@:
ret
filesearch_free_result:
mov ecx, [ebp+filesearch_data.result_blocks]
@@:
jecxz .ret
push dword [ecx]
call pgfree
pop ecx
jmp @b
.ret:
ret
filesearch_thread:
pop ebp
; initialize search for string
xor ecx, ecx
xor edx, edx
mov [ebp+filesearch_data.skip_errors_mask], cl
lea ebx, [ebp+filesearch_data.string]
cmp byte [ebx], dl
jz .noprepare
mov esi, tolower_table
test byte [ebp+filesearch_data.query_dlgdata+FileSearch_QueryTemplate.case.flags], 10h
jz @f
mov esi, identical_table
@@:
test byte [ebp+filesearch_data.query_dlgdata+FileSearch_QueryTemplate.whole.flags], 10h
setnz al
push eax
push ecx ; force cp866
call search_string_pre
.noprepare:
push -1
.enter_recursion:
xor esi, esi ; start position: zero
.read_folder_loop:
push esi
lea esi, [ebp+filesearch_data.curdir]
lea edi, [ebp+filesearch_data.curfile]
@@:
lodsb
stosb
test al, al
jnz @b
pop esi
.read_retry:
lea ebx, [ebp+filesearch_data.fs.func]
mov dword [ebx], 1
mov dword [ebx+4], esi
and dword [ebx+8], 0
mov dword [ebx+12], search_dir_query_size
lea eax, [ebp+filesearch_data.dir_area]
mov [ebx+16], eax
push SF_FILE
pop eax
int 40h
test eax, eax
jz .read_folder_ok
cmp eax, 6
jz .read_folder_ok
xor ebx, ebx
xchg ebx, dword [ebp+filesearch_data.dir_area+4]
test [ebp+filesearch_data.skip_errors_mask], filesearch_data.skip_read_folder
jnz .skip1
push edx
lea edx, [ebp+filesearch_data.curdir]
call recursive_read_folder_err
pop edx
jz .read_retry
cmp al, 2
jnz @f
dec eax
or [ebp+filesearch_data.skip_errors_mask], filesearch_data.skip_read_folder
@@:
cmp al, 1
jnz .cancel
.skip1:
.read_folder_ok:
imul ebx, 304
lea eax, [ebp+filesearch_data.dir_area+32]
add ebx, eax
.scan_folder_loop:
cmp eax, ebx
jae .scan_folder_done
; ignore special entries "." and ".."
cmp word [eax+40], '.'
jz .scan_folder_next
cmp word [eax+40], '..'
jnz @f
cmp byte [eax+42], 0
jz .scan_folder_next
@@:
call .check_stop
; construct name
push esi edi ebx eax
lea ebx, [ebp+filesearch_data.curfile+1023]
lea esi, [eax+40]
mov byte [edi-1], '/'
@@:
cmp edi, ebx
jae .namebig
lodsb
stosb
test al, al
jnz @b
pop eax
test byte [eax], 10h
jz .scan_file
; it is nested folder, enter recursion
; to maintain ASCIIZ string coherency, copy backward
lea esi, [edi+filesearch_data.curdir-filesearch_data.curfile]
@@:
dec edi
dec esi
mov al, [edi]
mov [esi], al
cmp al, '/'
jnz @b
mov [ebp+filesearch_data.datachanged], 1
pop ebx edi
jmp .enter_recursion
.namebig:
pop eax
mov byte [edi], 0
test [ebp+filesearch_data.skip_errors_mask], filesearch_data.skip_bigname
jnz .namebig.skip
push eax
push edi
test byte [eax], 10h
mov eax, aFileNameTooBig
jz @f
add eax, aFolderNameTooBig - aFileNameTooBig
@@:
push eax
mov eax, esp
push SkipOrCancelBtn
push 3
push eax
push 2
call SayErr
cmp al, 1
jnz @f
dec eax
or [ebp+filesearch_data.skip_errors_mask], filesearch_data.skip_bigname
@@:
test al, al
pop eax eax eax
jnz .cancel
.namebig.skip:
jmp .scan_folder_next_pop
.scan_file:
; it is a file
; first check: does file name match the mask?
push eax edx
; <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
lea esi, [eax+40]
lea edi, [ebp+filesearch_data.lowername]
push edi
xor eax, eax
@@:
lodsb
mov al, [tolower_table+eax]
stosb
test al, al
jnz @b
; <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
lea edx, [edi-1]
pop esi
lea edi, [ebp+filesearch_data.mask]
call match_mask_rev_lowercase
pop edx eax
jc .scan_folder_next_pop
; ok, second check: is the string present in this file?
jecxz .file_found
push eax
call filesearch_test_file
pop eax
jc .scan_folder_next_pop
.file_found:
push eax
; allocate memory for new result
lea esi, [ebp+filesearch_data.curfile]
mov ebx, esi
@@:
lodsb
test al, al
jnz @b
sub esi, ebx
mov eax, [ebp+filesearch_data.cur_result_ptr]
add esi, 8
push ecx
mov ecx, 0x4000
sub ecx, eax
cmp ecx, esi
jae .nonewblock
mov ecx, 0x4000
call xpgalloc
test eax, eax
jz .cancel
pushd [ebp+filesearch_data.result_blocks]
popd [eax]
mov [ebp+filesearch_data.result_blocks], eax
push 4
pop eax
mov [ebp+filesearch_data.cur_result_ptr], eax
.nonewblock:
add eax, [ebp+filesearch_data.result_blocks]
add [ebp+filesearch_data.cur_result_ptr], esi
pop ecx
; eax -> allocated memory, fill it
push eax
lea edi, [eax+8]
mov esi, ebx
@@:
lodsb
stosb
test al, al
jnz @b
pop eax
mov ebx, [ebp+filesearch_data.list.end]
mov [eax+4], ebx
and dword [eax], 0
mov [ebp+filesearch_data.list.end], eax
test ebx, ebx
jz @f
mov [ebx], eax
@@:
inc [ebp+filesearch_data.list.numitems]
cmp [ebp+filesearch_data.list.curitemptr], 0
jnz @f
mov [ebp+filesearch_data.list.curitemptr], eax
@@:
cmp [ebp+filesearch_data.list.head], 0
jnz @f
mov [ebp+filesearch_data.list.head], eax
@@:
mov [ebp+filesearch_data.datachanged], 1
pop eax
.scan_folder_next_pop:
pop ebx edi esi
mov byte [edi-1], 0
.scan_folder_next:
inc esi
add eax, 304
jmp .scan_folder_loop
.scan_folder_done:
cmp dword [ebp+filesearch_data.dir_area+4], search_dir_query_size
jz .read_folder_loop
pop esi
inc esi
jz .done
lea eax, [ebp+filesearch_data.curdir]
@@:
inc eax
cmp byte [eax], 0
jnz @b
@@:
dec eax
cmp byte [eax], '/'
jnz @b
mov byte [eax], 0
mov [ebp+filesearch_data.datachanged], 1
jmp .read_folder_loop
.cancel:
.done:
mov [ebp+filesearch_data.datachanged], 2
or eax, -1
int 40h
.check_stop:
cmp [ebp+filesearch_data.stop], 1
jz .cancel
ja @f
ret
@@:
push eax ebx
push SF_SLEEP
pop eax
push 1
pop ebx
int 40h
pop ebx eax
jmp .check_stop
filesearch_test_file:
lea ebx, [ebp+filesearch_data.fs.func]
lea eax, [ebp+filesearch_data.filebuf]
mov [ebx+16], eax
xor eax, eax
mov [ebx], eax
mov [ebx+4], eax
mov [ebx+8], eax
mov dword [ebx+12], search_filebuf_size
mov edi, edx
test byte [ebp+filesearch_data.query_dlgdata+FileSearch_QueryTemplate.whole.flags], 10h
jz .loop
add edi, 256
.loop:
.read_retry:
call filesearch_thread.check_stop
push SF_FILE
pop eax
lea ebx, [ebp+filesearch_data.fs.func]
int 40h
test eax, eax
jz .readok
cmp eax, 6
jz .readok
test [ebp+filesearch_data.skip_errors_mask], filesearch_data.skip_read_file
jnz .ret_failed
push edx
lea edx, [ebp+filesearch_data.curfile]
call recursive_read_file_err
pop edx
jz .read_retry
cmp al, 2
jnz @f
dec eax
or [ebp+filesearch_data.skip_errors_mask], filesearch_data.skip_read_file
@@:
cmp al, 1
jnz filesearch_thread.cancel
.ret_failed:
stc
ret
.readok:
test ebx, ebx
jz .eof
push ebx
lea esi, [ebp+filesearch_data.filebuf]
add ebx, esi
; edi = current state, edx -> FSM, ecx = last state,
; esi -> current data, ebx -> end of buffer
.scanloop: ; loop unrolled
; get current symbol
movzx eax, byte [esi]
; calculate next state
movzx edi, byte [edi+eax]
; done?
cmp edi, ecx
jz .ret_ok_pop
; no; proceed to next symbol
shl edi, 8
add edi, edx
cmp esi, ebx
jae .scandone
movzx eax, byte [esi+1]
add esi, 2
movzx edi, byte [edi+eax]
cmp edi, ecx
jz .ret_ok_pop
shl edi, 8
add edi, edx
cmp esi, ebx
jb .scanloop
.scandone:
pop ebx
.eof:
add [ebp+filesearch_data.fs.pos_low], ebx
adc [ebp+filesearch_data.fs.pos_high], 0
cmp ebx, search_filebuf_size
jz .loop
; EOF, last chance for whole-words-only search
test byte [ebp+filesearch_data.query_dlgdata+FileSearch_QueryTemplate.whole.flags], 10h
jz .ret_failed
movzx edi, byte [edi+' ']
cmp edi, ecx
jnz .ret_failed
clc
ret
.ret_ok_pop:
pop ebx
clc
ret
virtual at 0
_FILE:
.pos dq ?
.bufpos dq ?
.bufsize dd ?
.mode dd ?
.hPlugin dd ?
.hFile dd ?
.fileinfo:
.fimode dd ?
.fioffset dq ?
.fisize dd ?
.fibuf dd ?
.finame rb 1024
.attr rb 40
align 512
.buf rb 2048
.size = $
end virtual
O_READ = 1 ; allows read from file
O_WRITE = 2 ; allows write to file
O_CREATE = 4 ; if file does not exist and this flag is set, create file;
; if file does not exist and this flag is not set, fail
O_TRUNCATE = 8 ; truncate file if it exists
O_SEQUENTIAL_ONLY = 10h ; there will be no 'seek'/'setpos' calls
; HANDLE __stdcall open(const char* name, int mode);
; Opens physical file
open:
pushad
mov ecx, _FILE.size
call xpgalloc
test eax, eax
jz .ret0z
mov [esp+28], eax
mov ecx, eax
mov esi, [esp+36]
lea edi, [eax+_FILE.finame]
lea edx, [eax+_FILE.finame+1024]
@@:
lodsb
stosb
test al, al
jz @f
cmp edi, edx
jb @b
.ret0:
call pgfree
.ret0z:
popad
xor eax, eax
ret 8
@@:
mov eax, [esp+40]
mov [ecx+_FILE.mode], eax
.getattr:
lea edi, [ecx+_FILE.fileinfo]
mov ebx, edi
push 5
pop eax
stosd
xor eax, eax
stosd
stosd
stosd
lea eax, [ecx+_FILE.attr]
stosd
push SF_FILE
pop eax
int 0x40
test eax, eax
jz .found
cmp eax, 5
jnz .ret0
; file does not exist
test [ecx+_FILE.mode], O_CREATE
jz .ret0
.truncate:
lea ebx, [ecx+_FILE.fileinfo]
mov byte [ebx], 2
push SF_FILE
pop eax
int 0x40
test eax, eax
jz .getattr
jmp .ret0
.found:
test [ecx+_FILE.mode], O_TRUNCATE
jz @f
cmp dword [ecx+_FILE.attr+36], eax
jnz .truncate
cmp dword [ecx+_FILE.attr+32], eax
jnz .truncate
@@:
mov dword [ecx+_FILE.pos], eax
mov dword [ecx+_FILE.pos+4], eax
mov dword [ecx+_FILE.bufpos], eax
mov dword [ecx+_FILE.bufpos+4], eax
mov [ecx+_FILE.bufsize], eax
mov [ecx+_FILE.hPlugin], eax
mov [ecx+_FILE.hFile], eax
mov dword [ecx+_FILE.fioffset], eax
mov dword [ecx+_FILE.fioffset+4], eax
mov [esp+28], ecx
popad
ret 8
; HANDLE __stdcall open2(int plugin_id, HANDLE plugin_instance, const char* name, int mode);
; Opens file on plugin panel
open2:
cmp dword [esp+4], 0
jnz .plugin
pop eax
add esp, 8
push eax
jmp open
.plugin:
pushad
mov ecx, _FILE.size
call xpgalloc
test eax, eax
jz .ret0z
mov [esp+28], eax
mov ecx, eax
mov esi, [esp+44]
lea edi, [eax+_FILE.finame]
lea edx, [eax+_FILE.finame+1024]
@@:
lodsb
stosb
test al, al
jz @f
cmp edi, edx
jb @b
.ret0:
call pgfree
.ret0z:
popad
xor eax, eax
ret 8
@@:
mov edx, [esp+36]
mov [ecx+_FILE.hPlugin], edx
mov ebx, [esp+40]
mov eax, [esp+48]
mov [ecx+_FILE.mode], eax
push ebx ecx
push eax
lea eax, [ecx+_FILE.finame]
push eax
push ebx
call [edx+PluginInfo.open]
pop ecx ebx
test eax, eax
jz .ret0
mov [ecx+_FILE.hFile], eax
mov edx, [esp+36]
push ecx
lea edi, [ecx+_FILE.fileinfo]
push edi
xor eax, eax
push ecx
push 10
pop ecx
rep stosd
pop ecx
lea eax, [ecx+_FILE.finame]
push eax
push ebx
call [edx+PluginInfo.getattr]
pop ecx
xor eax, eax
mov dword [ecx+_FILE.pos], eax
mov dword [ecx+_FILE.pos+4], eax
mov dword [ecx+_FILE.bufpos], eax
mov dword [ecx+_FILE.bufpos+4], eax
mov [ecx+_FILE.bufsize], eax
mov dword [ecx+_FILE.fioffset], eax
mov dword [ecx+_FILE.fioffset+4], eax
mov [esp+28], ecx
popad
ret 16
; unsigned __stdcall read(HANDLE hFile, void* buf, unsigned size);
read:
xor eax, eax
pushad
mov ecx, [esp+36]
test [ecx+_FILE.mode], O_READ
jnz @f
.ret:
popad
ret 12
@@:
cmp dword [esp+44], eax
jz .ret
mov [ecx+_FILE.fimode], eax
mov ebx, [ecx+_FILE.bufsize]
mov eax, dword [ecx+_FILE.pos]
and eax, 2047
sub ebx, eax
jbe .nobuf0
cmp ebx, [esp+44]
jbe @f
mov ebx, [esp+44]
@@:
push ecx
lea esi, [ecx+eax+_FILE.buf]
mov ecx, ebx
mov edi, [esp+44]
rep movsb
pop ecx
mov [esp+40], edi
add [esp+28], ebx
add dword [ecx+_FILE.pos], ebx
adc dword [ecx+_FILE.pos+4], 0
test dword [ecx+_FILE.pos], 2047
jnz @f
and [ecx+_FILE.bufsize], 0
@@:
sub [esp+44], ebx
jz .ret
.nobuf0:
test dword [ecx+_FILE.pos], 2047
jz .aligned
cmp dword [ecx+_FILE.bufsize], 0
jnz .ret
lea ebx, [ecx+_FILE.fileinfo]
mov dword [ebx+12], 2048
lea eax, [ecx+_FILE.buf]
mov dword [ebx+16], eax
mov eax, dword [ecx+_FILE.fioffset]
mov dword [ecx+_FILE.bufpos], eax
mov eax, dword [ecx+_FILE.fioffset+4]
mov dword [ecx+_FILE.bufpos+4], eax
call .doread
test eax, eax
jnz .ret
mov [ecx+_FILE.bufsize], ebx
mov eax, dword [ecx+_FILE.pos]
and eax, 2047
sub ebx, eax
jbe .ret
cmp ebx, [esp+44]
jbe @f
mov ebx, [esp+44]
@@:
push ecx
lea esi, [ecx+eax+_FILE.buf]
mov ecx, ebx
mov edi, [esp+44]
rep movsb
pop ecx
add dword [ecx+_FILE.pos], ebx
adc dword [ecx+_FILE.pos+4], 0
mov [esp+40], edi
add [esp+28], ebx
sub [esp+44], ebx
jz .ret
test dword [ecx+_FILE.pos], 2047
jnz .ret
.aligned:
lea ebx, [ecx+_FILE.fileinfo]
mov eax, [esp+44]
and eax, not 2047
jz .finish
and [ecx+_FILE.bufsize], 0
mov [ebx+12], eax
mov eax, [esp+40]
mov [ebx+16], eax
call .doread
test eax, eax
jnz .ret
add dword [ecx+_FILE.pos], ebx
adc dword [ecx+_FILE.pos+4], 0
add [esp+28], ebx
add [esp+40], ebx
sub [esp+44], ebx
jz .ret
cmp ebx, [ecx+_FILE.fisize]
jb .ret
.finish:
lea ebx, [ecx+_FILE.fileinfo]
mov dword [ebx+12], 2048
lea eax, [ecx+_FILE.buf]
mov [ebx+16], eax
and [ecx+_FILE.bufsize], 0
mov eax, dword [ecx+_FILE.fioffset]
mov dword [ecx+_FILE.bufpos], eax
mov eax, dword [ecx+_FILE.fioffset+4]
mov dword [ecx+_FILE.bufpos+4], eax
call .doread
test eax, eax
jnz .ret
mov [ecx+_FILE.bufsize], ebx
cmp ebx, [esp+44]
jb @f
mov ebx, [esp+44]
@@:
add [esp+28], ebx
add dword [ecx+_FILE.pos], ebx
adc dword [ecx+_FILE.pos+4], 0
lea esi, [ecx+_FILE.buf]
mov edi, [esp+40]
mov ecx, ebx
rep movsb
popad
ret 12
.doread:
mov eax, [ecx+_FILE.hPlugin]
test eax, eax
jz .native
push ecx
push [ecx+_FILE.fisize]
push [ecx+_FILE.fibuf]
push [ecx+_FILE.hFile]
call [eax+PluginInfo.read]
pop ecx
cmp eax, -1
jz @f
mov ebx, eax
xor eax, eax
jmp .addpos
@@:
ret
.native:
push SF_FILE
pop eax
int 0x40
test eax, eax
jz .addpos
cmp eax, 6
jnz @b
xor eax, eax
.addpos:
add dword [ecx+_FILE.fioffset], ebx
adc dword [ecx+_FILE.fioffset+4], 0
ret
; void __stdcall seek(HANDLE hFile, int method, __int64 newpos);
seek:
pushad
mov ecx, [esp+36]
mov eax, [esp+44]
mov edx, [esp+48]
cmp dword [esp+40], 1
jb .set
ja .end
add eax, dword [ecx+_FILE.pos]
adc edx, dword [ecx+_FILE.pos+4]
jmp .set
.end:
add eax, dword [ecx+_FILE.attr+32]
adc edx, dword [ecx+_FILE.attr+36]
.set:
mov dword [ecx+_FILE.pos], eax
mov dword [ecx+_FILE.pos+4], edx
and eax, not 2047
cmp eax, dword [ecx+_FILE.bufpos]
jnz @f
cmp edx, dword [ecx+_FILE.bufpos+4]
jz .bufposok
@@:
and [ecx+_FILE.bufsize], 0
mov dword [ecx+_FILE.bufpos], eax
mov dword [ecx+_FILE.bufpos+4], edx
.bufposok:
cmp [ecx+_FILE.bufsize], 0
jnz .ret
cmp eax, dword [ecx+_FILE.fioffset]
jnz @f
cmp edx, dword [ecx+_FILE.fioffset+4]
jz .ret
@@:
mov dword [ecx+_FILE.fioffset], eax
mov dword [ecx+_FILE.fioffset+4], edx
mov eax, [ecx+_FILE.hPlugin]
test eax, eax
jz @f
push dword [ecx+_FILE.fioffset+4]
push dword [ecx+_FILE.fioffset]
push [ecx+_FILE.hFile]
call [eax+PluginInfo.setpos]
@@:
.ret:
popad
ret 16
setpos_default:
push dword [esp+12]
push dword [esp+12]
push 0
push dword [esp+16]
call seek
ret 12
; __int64 __stdcall tell(HANDLE hFile);
tell:
mov eax, [esp+4]
mov edx, dword [eax+_FILE.pos+4]
mov eax, dword [eax+_FILE.pos]
ret 4
; __int64 __stdcall filesize(HANDLE hFile);
filesize:
mov eax, [esp+4]
mov edx, dword [eax+_FILE.attr+36]
mov eax, dword [eax+_FILE.attr+32]
ret 4
; void __stdcall close(HANDLE hFile);
close:
pushad
mov ecx, [esp+24h]
mov eax, [ecx+_FILE.hPlugin]
test eax, eax
jz @f
push ecx
push [ecx+_FILE.hFile]
call [eax+PluginInfo.close]
pop ecx
@@:
call pgfree
popad
ret 4
getattr_default:
mov eax, 2
ret 12