530 lines
11 KiB
Plaintext
530 lines
11 KiB
Plaintext
|
|
; flat editor core
|
|
; Copyright (c) 1999-2015, Tomasz Grysztar.
|
|
; All rights reserved.
|
|
|
|
find_first:
|
|
mov [search_flags],eax
|
|
call release_search_data
|
|
or esi,esi
|
|
jz nothing_to_search_for
|
|
mov edi,esi
|
|
xor al,al
|
|
xor ecx,ecx
|
|
sub ecx,edi
|
|
repne scasb
|
|
lea ebx,[edi-1]
|
|
sub ebx,esi
|
|
jz nothing_to_search_for
|
|
lea ecx,[(256+ebx)*4+ebx]
|
|
push ebx
|
|
call get_memory
|
|
or eax,eax
|
|
jz not_enough_memory
|
|
mov [search_data],eax
|
|
mov [search_handle],ebx
|
|
pop ebx
|
|
mov edi,eax
|
|
lea ecx,[256+ebx]
|
|
mov eax,ebx
|
|
rep stosd
|
|
mov ecx,ebx
|
|
mov ebx,[search_data]
|
|
mov edx,ecx
|
|
test [search_flags],FEFIND_BACKWARD
|
|
jnz text_for_backward_search
|
|
test [search_flags],FEFIND_CASESENSITIVE
|
|
jnz copy_search_text
|
|
push ebx
|
|
mov ebx,upper_case_table
|
|
convert_search_text:
|
|
lodsb
|
|
xlatb
|
|
stosb
|
|
loop convert_search_text
|
|
pop ebx
|
|
jmp make_character_shifts_table
|
|
copy_search_text:
|
|
rep movsb
|
|
jmp make_character_shifts_table
|
|
text_for_backward_search:
|
|
add edi,ecx
|
|
mov edx,ecx
|
|
push ebx
|
|
mov ebx,upper_case_table
|
|
reverse_search_text:
|
|
lodsb
|
|
test [search_flags],FEFIND_CASESENSITIVE
|
|
jnz reverse_store_character
|
|
xlatb
|
|
reverse_store_character:
|
|
dec edi
|
|
mov [edi],al
|
|
dec ecx
|
|
jnz reverse_search_text
|
|
pop ebx
|
|
add edi,edx
|
|
xor ecx,ecx
|
|
make_character_shifts_table:
|
|
cmp edx,ecx
|
|
je character_shifts_table_ok
|
|
dec edi
|
|
jecxz character_shift_ok
|
|
mov al,[edi]
|
|
cmp [ebx+eax*4],edx
|
|
jne character_shift_ok
|
|
mov [ebx+eax*4],ecx
|
|
character_shift_ok:
|
|
inc ecx
|
|
jmp make_character_shifts_table
|
|
character_shifts_table_ok:
|
|
lea edi,[ebx+(256+ecx)*4]
|
|
push edi
|
|
lea edi,[edi+ecx-2]
|
|
movzx eax,byte [edi+1]
|
|
mov edx,[ebx+eax*4]
|
|
mov [ebx+256*4],edx
|
|
cmp ecx,1
|
|
je suffix_match_shifts_table_done
|
|
mov ecx,2
|
|
mov esi,edi
|
|
sub esi,edx
|
|
make_suffix_match_shifts_table:
|
|
cmp esi,[esp]
|
|
jb store_suffix_match_shift
|
|
mov al,[esi]
|
|
cmp al,[edi]
|
|
je store_suffix_match_shift
|
|
find_suffix_match:
|
|
dec esi
|
|
inc edx
|
|
cmp esi,[esp]
|
|
jb match_part_of_suffix
|
|
push ecx esi edi
|
|
repe cmpsb
|
|
pop edi esi ecx
|
|
jne find_suffix_match
|
|
jmp store_suffix_match_shift
|
|
match_part_of_suffix:
|
|
mov eax,[esp]
|
|
push ecx esi edi
|
|
xchg eax,esi
|
|
sub eax,esi
|
|
add ecx,eax
|
|
repe cmpsb
|
|
pop edi esi ecx
|
|
jne suffix_match_shifts_table_done
|
|
store_suffix_match_shift:
|
|
mov [ebx+256*4+(ecx-1)*4],edx
|
|
dec esi
|
|
dec edi
|
|
inc ecx
|
|
cmp ecx,[ebx]
|
|
jbe make_suffix_match_shifts_table
|
|
suffix_match_shifts_table_done:
|
|
pop eax
|
|
|
|
find_next:
|
|
mov edi,[search_data]
|
|
or edi,edi
|
|
jz nothing_to_search_for
|
|
push [caret_line]
|
|
push [caret_line_number]
|
|
push [caret_position]
|
|
push [selection_position]
|
|
test [search_flags],FEFIND_BACKWARD
|
|
jnz search_backward
|
|
test [search_flags],FEFIND_INWHOLETEXT
|
|
jz search_for_text
|
|
mov eax,[first_line]
|
|
mov [caret_line],eax
|
|
xor eax,eax
|
|
mov [caret_position],eax
|
|
inc eax
|
|
mov [caret_line_number],eax
|
|
search_for_text:
|
|
mov ecx,[edi]
|
|
dec ecx
|
|
add ecx,[caret_position]
|
|
mov esi,[caret_line]
|
|
cmp ecx,[peak_line_length]
|
|
jae text_not_in_this_line
|
|
mov [caret_position],ecx
|
|
call get_caret_segment
|
|
mov edi,[search_data]
|
|
mov eax,[edi]
|
|
lea ebx,[edi+(256+eax)*4]
|
|
mov ah,[ebx+eax-1]
|
|
mov ebx,upper_case_table
|
|
search_in_line:
|
|
cmp edx,SEGMENT_DATA_LENGTH
|
|
jae text_not_in_this_line
|
|
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
|
|
test [search_flags],FEFIND_CASESENSITIVE
|
|
jnz compare_last_character
|
|
xlatb
|
|
compare_last_character:
|
|
cmp al,ah
|
|
je partial_match
|
|
mismatch_shift:
|
|
movzx ecx,al
|
|
mov ecx,[edi+ecx*4]
|
|
shift_search_position:
|
|
add edx,ecx
|
|
add ecx,[caret_position]
|
|
cmp ecx,[peak_line_length]
|
|
jae text_not_in_this_line
|
|
mov [caret_position],ecx
|
|
check_search_position:
|
|
cmp edx,SEGMENT_DATA_LENGTH
|
|
jb search_in_line
|
|
mov ecx,[esi]
|
|
btr ecx,0
|
|
jnc search_in_line
|
|
sub edx,SEGMENT_DATA_LENGTH
|
|
mov esi,ecx
|
|
jmp check_search_position
|
|
partial_match:
|
|
mov ecx,[edi]
|
|
dec ecx
|
|
jz text_found
|
|
push edi
|
|
lea edi,[edi+(256+ecx+1)*4]
|
|
lea edi,[edi+ecx]
|
|
compare_text:
|
|
sub edx,1
|
|
jc compare_in_previous_segment
|
|
dec edi
|
|
mov al,20h
|
|
cmp edx,SEGMENT_DATA_LENGTH
|
|
jae compare_character
|
|
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
|
|
test [search_flags],FEFIND_CASESENSITIVE
|
|
jnz compare_character
|
|
xlatb
|
|
compare_character:
|
|
cmp al,[edi]
|
|
loope compare_text
|
|
pop edi
|
|
je text_found
|
|
neg ecx
|
|
add ecx,[edi]
|
|
dec ecx
|
|
add edx,ecx
|
|
mov ecx,[edi+(256+ecx-1)*4]
|
|
jmp shift_search_position
|
|
compare_in_previous_segment:
|
|
mov esi,[esi+4]
|
|
and esi,not 1
|
|
mov edx,SEGMENT_DATA_LENGTH
|
|
jmp compare_text
|
|
text_not_in_this_line:
|
|
mov esi,[esi]
|
|
or esi,esi
|
|
jz text_not_found
|
|
btr esi,0
|
|
jc text_not_in_this_line
|
|
search_in_next_line:
|
|
mov [caret_line],esi
|
|
inc [caret_line_number]
|
|
mov [caret_position],0
|
|
mov edi,[search_data]
|
|
jmp search_for_text
|
|
text_found:
|
|
mov eax,[caret_position]
|
|
inc eax
|
|
mov [selection_position],eax
|
|
sub eax,[edi]
|
|
mov [caret_position],eax
|
|
jz left_text_edge_ok
|
|
test [search_flags],FEFIND_WHOLEWORDS
|
|
jz left_text_edge_ok
|
|
mov edi,[search_data]
|
|
mov ecx,[edi]
|
|
mov al,[edi+(256+ecx)*4]
|
|
call recognize_character
|
|
jc left_text_edge_ok
|
|
dec [caret_position]
|
|
call get_caret_segment
|
|
inc [caret_position]
|
|
cmp edx,SEGMENT_DATA_LENGTH
|
|
jae left_text_edge_ok
|
|
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
|
|
call recognize_character
|
|
jnc found_not_acceptable
|
|
left_text_edge_ok:
|
|
mov eax,[caret_position]
|
|
xchg eax,[selection_position]
|
|
mov [caret_position],eax
|
|
mov edi,[search_data]
|
|
mov ecx,[edi]
|
|
lea edi,[edi+(256+ecx)*4]
|
|
mov al,[edi+ecx-1]
|
|
cmp al,20h
|
|
je right_text_edge_blank
|
|
test [search_flags],FEFIND_WHOLEWORDS
|
|
jz right_text_edge_ok
|
|
call recognize_character
|
|
jc right_text_edge_ok
|
|
call get_caret_segment
|
|
cmp edx,SEGMENT_DATA_LENGTH
|
|
jae right_text_edge_ok
|
|
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
|
|
call recognize_character
|
|
jc right_text_edge_ok
|
|
mov eax,[selection_position]
|
|
mov [caret_position],eax
|
|
found_not_acceptable:
|
|
mov edi,[search_data]
|
|
mov ecx,[edi]
|
|
mov eax,[edi+(256+ecx-1)*4]
|
|
add [caret_position],eax
|
|
jmp search_for_text
|
|
right_text_edge_blank:
|
|
call get_caret_segment
|
|
check_for_blank_end:
|
|
mov ecx,SEGMENT_DATA_LENGTH
|
|
sub ecx,edx
|
|
jz blank_end_next_segment
|
|
push edi
|
|
mov al,20h
|
|
lea edi,[esi+SEGMENT_HEADER_LENGTH+edx]
|
|
repe scasb
|
|
pop edi
|
|
jne right_text_edge_ok
|
|
blank_end_next_segment:
|
|
mov esi,[esi]
|
|
or esi,esi
|
|
jz text_not_found
|
|
btr esi,0
|
|
jnc search_in_next_line
|
|
xor edx,edx
|
|
jmp check_for_blank_end
|
|
right_text_edge_ok:
|
|
mov eax,[caret_line]
|
|
mov ecx,[caret_line_number]
|
|
mov [selection_line],eax
|
|
mov [selection_line_number],ecx
|
|
and [search_flags],not FEFIND_INWHOLETEXT
|
|
add esp,16
|
|
clc
|
|
retn
|
|
text_not_found:
|
|
pop [selection_position]
|
|
pop [caret_position]
|
|
pop [caret_line_number]
|
|
pop [caret_line]
|
|
nothing_to_search_for:
|
|
stc
|
|
retn
|
|
search_backward:
|
|
test [search_flags],FEFIND_INWHOLETEXT
|
|
jz backward_search_for_text
|
|
or eax,-1
|
|
call find_line
|
|
mov [caret_line],esi
|
|
mov [caret_line_number],ecx
|
|
call move_to_line_end
|
|
backward_search_for_text:
|
|
mov ecx,[caret_position]
|
|
sub ecx,1
|
|
jc backward_text_not_in_this_line
|
|
mov [caret_position],ecx
|
|
mov edi,[search_data]
|
|
mov eax,[edi]
|
|
mov al,[edi+(256+eax)*4]
|
|
cmp al,20h
|
|
jne backward_search_starting_position_ok
|
|
mov esi,[caret_line]
|
|
mov ecx,[esi+8]
|
|
mov edi,[search_data]
|
|
mov eax,[edi]
|
|
sub ecx,eax
|
|
jc backward_text_not_in_this_line
|
|
cmp ecx,[caret_position]
|
|
jae backward_search_starting_position_ok
|
|
mov [caret_position],ecx
|
|
backward_search_starting_position_ok:
|
|
call get_caret_segment
|
|
mov edi,[search_data]
|
|
mov eax,[edi]
|
|
lea ebx,[edi+(256+eax)*4]
|
|
mov ah,[ebx+eax-1]
|
|
mov ebx,upper_case_table
|
|
cmp edx,SEGMENT_DATA_LENGTH
|
|
jb backward_search_in_line
|
|
mov ecx,edx
|
|
sub ecx,SEGMENT_DATA_LENGTH-1
|
|
sub edx,ecx
|
|
sub [caret_position],ecx
|
|
backward_search_in_line:
|
|
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
|
|
test [search_flags],FEFIND_CASESENSITIVE
|
|
jnz compare_first_character
|
|
xlatb
|
|
compare_first_character:
|
|
cmp al,ah
|
|
je backward_partial_match
|
|
backward_mismatch_shift:
|
|
movzx ecx,al
|
|
mov ecx,[edi+ecx*4]
|
|
shift_backward_search_position:
|
|
sub edx,ecx
|
|
sub [caret_position],ecx
|
|
jc backward_text_not_in_this_line
|
|
check_backward_search_position:
|
|
cmp edx,0
|
|
jge backward_search_in_line
|
|
mov esi,[esi+4]
|
|
and esi,not 1
|
|
add edx,SEGMENT_DATA_LENGTH
|
|
jmp check_backward_search_position
|
|
backward_partial_match:
|
|
mov ecx,[edi]
|
|
dec ecx
|
|
jz backward_text_found
|
|
push edi
|
|
lea edi,[edi+(256+ecx+1)*4]
|
|
lea edi,[edi+ecx]
|
|
backward_compare_text:
|
|
inc edx
|
|
cmp edx,SEGMENT_DATA_LENGTH
|
|
jae compare_in_next_segment
|
|
dec edi
|
|
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
|
|
test [search_flags],FEFIND_CASESENSITIVE
|
|
jnz backward_compare_character
|
|
xlatb
|
|
backward_compare_character:
|
|
cmp al,[edi]
|
|
loope backward_compare_text
|
|
pop edi
|
|
je backward_text_found
|
|
neg ecx
|
|
add ecx,[edi]
|
|
dec ecx
|
|
sub edx,ecx
|
|
mov ecx,[edi+(256+ecx)*4]
|
|
jmp shift_backward_search_position
|
|
compare_in_next_segment:
|
|
sub edx,SEGMENT_DATA_LENGTH
|
|
mov esi,[esi]
|
|
btr esi,0
|
|
jnc compare_blank_space
|
|
dec edx
|
|
jmp backward_compare_text
|
|
compare_blank_space:
|
|
pop edi
|
|
cmp ecx,[edi]
|
|
jbe backward_text_found
|
|
backward_text_not_in_this_line:
|
|
mov esi,[caret_line]
|
|
mov esi,[esi+4]
|
|
or esi,esi
|
|
jz text_not_found
|
|
mov [caret_line],esi
|
|
dec [caret_line_number]
|
|
mov ecx,[peak_line_length]
|
|
mov [caret_position],ecx
|
|
jmp backward_search_for_text
|
|
backward_text_found:
|
|
test [search_flags],FEFIND_WHOLEWORDS
|
|
jz backward_left_text_edge_ok
|
|
cmp [caret_position],0
|
|
je backward_left_text_edge_ok
|
|
mov edi,[search_data]
|
|
mov ecx,[edi]
|
|
lea edi,[edi+(256+ecx)*4]
|
|
mov al,[edi+ecx-1]
|
|
call recognize_character
|
|
jc backward_left_text_edge_ok
|
|
dec [caret_position]
|
|
call get_caret_segment
|
|
inc [caret_position]
|
|
cmp edx,SEGMENT_DATA_LENGTH
|
|
jae backward_left_text_edge_ok
|
|
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
|
|
call recognize_character
|
|
jnc backward_found_not_acceptable
|
|
backward_left_text_edge_ok:
|
|
mov eax,[caret_position]
|
|
mov [selection_position],eax
|
|
mov edi,[search_data]
|
|
mov ecx,[edi]
|
|
add eax,ecx
|
|
mov [caret_position],eax
|
|
test [search_flags],FEFIND_WHOLEWORDS
|
|
jz backward_right_text_edge_ok
|
|
mov al,[edi+(256+ecx)*4]
|
|
call recognize_character
|
|
jc backward_right_text_edge_ok
|
|
call get_caret_segment
|
|
cmp edx,SEGMENT_DATA_LENGTH
|
|
jae backward_right_text_edge_ok
|
|
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
|
|
call recognize_character
|
|
jc backward_right_text_edge_ok
|
|
mov eax,[selection_position]
|
|
mov [caret_position],eax
|
|
backward_found_not_acceptable:
|
|
mov edi,[search_data]
|
|
mov ecx,[edi]
|
|
mov eax,[edi+(256+ecx-1)*4]
|
|
sub [caret_position],eax
|
|
jbe backward_text_not_in_this_line
|
|
jmp backward_search_for_text
|
|
backward_right_text_edge_ok:
|
|
mov eax,[caret_position]
|
|
xchg eax,[selection_position]
|
|
mov [caret_position],eax
|
|
mov eax,[caret_line]
|
|
mov ecx,[caret_line_number]
|
|
mov [selection_line],eax
|
|
mov [selection_line_number],ecx
|
|
and [search_flags],not FEFIND_INWHOLETEXT
|
|
add esp,16
|
|
clc
|
|
retn
|
|
|
|
get_search_text_length:
|
|
mov ecx,[search_data]
|
|
test ecx,ecx
|
|
jz no_search_text
|
|
mov ecx,[ecx]
|
|
clc
|
|
retn
|
|
get_search_text:
|
|
mov esi,[search_data]
|
|
test esi,esi
|
|
jz no_search_text
|
|
mov ecx,[esi]
|
|
lea esi,[esi+(256+ecx)*4]
|
|
test [search_flags],FEFIND_BACKWARD
|
|
jnz copy_inverted_text
|
|
rep movsb
|
|
xor al,al
|
|
stosb
|
|
clc
|
|
retn
|
|
copy_inverted_text:
|
|
mov al,[esi+ecx-1]
|
|
stosb
|
|
loop copy_inverted_text
|
|
xor al,al
|
|
stosb
|
|
clc
|
|
retn
|
|
no_search_text:
|
|
stc
|
|
retn
|
|
|
|
release_search_data:
|
|
mov edi,[search_data]
|
|
test edi,edi
|
|
jz search_data_released
|
|
mov ebx,[search_handle]
|
|
call release_memory
|
|
mov [search_data],0
|
|
search_data_released:
|
|
retn
|