asm_dip/toolchain/fasm2/source/ide/navigate.inc
2024-11-25 00:04:53 -05:00

512 lines
9.9 KiB
PHP

; flat editor core
; Copyright (c) 1999-2015, Tomasz Grysztar.
; All rights reserved.
find_line:
mov esi,[first_line]
mov ecx,1
mov edx,[window_line_number]
cmp eax,edx
jae forward_from_window
sub edx,eax
cmp edx,eax
jb backward_from_window
jmp find_forward
forward_from_window:
mov esi,[window_line]
mov ecx,edx
find_forward:
cmp ecx,eax
je line_found
cmp dword [esi],0
je line_found
mov ebx,esi
forward_skip_line:
mov ebx,[ebx]
btr ebx,0
jc forward_skip_line
or ebx,ebx
jz line_found
mov esi,ebx
inc ecx
jmp find_forward
backward_from_window:
mov esi,[window_line]
mov ecx,[window_line_number]
find_backward:
cmp ecx,eax
je line_found
cmp dword [esi+4],0
je line_found
mov esi,[esi+4]
dec ecx
jmp find_backward
line_found:
retn
get_caret_segment:
mov edx,[caret_position]
mov esi,[caret_line]
find_segment:
cmp edx,SEGMENT_DATA_LENGTH
jb segment_found
test byte [esi],1
jz segment_found
mov esi,[esi]
dec esi
sub edx,SEGMENT_DATA_LENGTH
jmp find_segment
segment_found:
retn
check_line_length:
xor edx,edx
mov ebx,esi
count_line_segments:
test byte [esi],1
jz last_line_segment
mov esi,[esi]
dec esi
add edx,SEGMENT_DATA_LENGTH
jmp count_line_segments
last_line_segment:
lea edi,[esi+SEGMENT_LENGTH-1]
mov al,20h
mov ecx,SEGMENT_DATA_LENGTH
std
repe scasb
cld
setne al
movzx eax,al
add ecx,eax
jnz line_segments_ok
or edx,edx
jz line_segments_ok
call store_freed_segment_for_undo
mov eax,[esi]
mov esi,[esi+4]
dec esi
call store_segment_for_undo
mov [esi],eax
sub edx,SEGMENT_DATA_LENGTH
jmp last_line_segment
line_segments_ok:
add ecx,edx
mov edx,ecx
cmp edx,[ebx+8]
je line_length_checked
mov esi,ebx
call store_segment_for_undo
xchg [ebx+8],edx
push edx
mov eax,[ebx+8]
call register_length
pop eax
call unregister_length
line_length_checked:
retn
register_length:
cmp eax,[peak_line_length]
jbe peak_length_ok
mov [peak_line_length],eax
peak_length_ok:
or eax,eax
jz ignore_zero_length
push ebx
call find_lengths_segment
inc dword [ebx+SEGMENT_HEADER_LENGTH+eax*4]
pop ebx
ignore_zero_length:
retn
find_lengths_segment:
mov ebx,[lengths_table]
try_lengths_segment:
cmp eax,SEGMENT_DATA_LENGTH/4
jb length_entry_ok
sub eax,SEGMENT_DATA_LENGTH/4
cmp dword [ebx],0
je add_lengths_segment
mov ebx,[ebx]
jmp try_lengths_segment
add_lengths_segment:
push eax ecx edi
call allocate_segment
jc memory_shortage
call store_allocated_segment_for_undo
mov [ebx],eax
mov edi,eax
xor eax,eax
stosd
mov eax,ebx
stosd
mov eax,[ebx+8]
add eax,SEGMENT_DATA_LENGTH/4
stosd
add edi,SEGMENT_HEADER_LENGTH-12
mov ecx,SEGMENT_DATA_LENGTH shr 2
xor eax,eax
rep stosd
lea ebx,[edi-SEGMENT_LENGTH]
pop edi ecx eax
jmp try_lengths_segment
length_entry_ok:
retn
unregister_length:
or eax,eax
jz ignore_zero_length
push ebx
cmp eax,[peak_line_length]
je unregister_peak_length
call find_lengths_segment
dec dword [ebx+SEGMENT_HEADER_LENGTH+eax*4]
length_unregistered:
pop ebx
retn
unregister_peak_length:
call find_lengths_segment
dec dword [ebx+SEGMENT_HEADER_LENGTH+eax*4]
jnz length_unregistered
find_reduced_peak:
or eax,eax
jz try_earlier_lengths_segment
dec eax
cmp dword [ebx+SEGMENT_HEADER_LENGTH+eax*4],0
je find_reduced_peak
add eax,[ebx+8]
mov [peak_line_length],eax
jmp length_unregistered
try_earlier_lengths_segment:
mov ebx,[ebx+4]
mov eax,SEGMENT_DATA_LENGTH/4
or ebx,ebx
jnz find_reduced_peak
mov [peak_line_length],ebx
jmp length_unregistered
update_window:
mov edx,[window_line_number]
cmp edx,1
je window_vertical_position_ok
add edx,[window_height]
dec edx
cmp edx,[lines_count]
jle window_vertical_position_ok
sub edx,[lines_count]
window_vertical_correction:
mov esi,[window_line]
mov esi,[esi+4]
or esi,esi
jz window_vertical_position_ok
mov [window_line],esi
dec [window_line_number]
dec edx
jnz window_vertical_correction
window_vertical_position_ok:
mov ecx,[peak_line_length]
cmp ecx,[caret_position]
jae caret_position_ok
mov ecx,[caret_position]
caret_position_ok:
cmp [selection_line],0
je selection_position_ok
cmp ecx,[selection_position]
jae selection_position_ok
mov ecx,[selection_position]
selection_position_ok:
mov eax,[window_width]
dec eax
cmp ecx,eax
jae edit_space_width_ok
mov ecx,eax
edit_space_width_ok:
mov [maximum_position],ecx
mov edx,[window_position]
or edx,edx
jz window_horizontal_position_ok
add edx,[window_width]
inc ecx
cmp edx,ecx
jbe window_horizontal_position_ok
sub edx,ecx
sub [window_position],edx
jnc window_horizontal_position_ok
mov [window_position],0
window_horizontal_position_ok:
retn
let_caret_appear:
mov eax,[caret_position]
cmp eax,[window_position]
jl horizontal_correction
mov ecx,[window_width]
jecxz last_position_ok
dec ecx
last_position_ok:
add ecx,[window_position]
mov eax,[caret_position]
sub eax,ecx
jbe horizontal_ok
add eax,[window_position]
horizontal_correction:
mov [window_position],eax
horizontal_ok:
mov esi,[caret_line]
mov ecx,[caret_line_number]
cmp ecx,[window_line_number]
jl vertical_correction
mov eax,[window_height]
or eax,eax
jz vertical_check
dec eax
vertical_check:
neg eax
add eax,[caret_line_number]
cmp [window_line_number],eax
jge vertical_ok
mov esi,[window_line]
mov ecx,[window_line_number]
vertical_find:
mov esi,[esi]
btr esi,0
jc vertical_find
inc ecx
cmp ecx,eax
jl vertical_find
vertical_correction:
mov [window_line],esi
mov [window_line_number],ecx
vertical_ok:
retn
move_line_up:
mov esi,[caret_line]
mov eax,[esi+4]
or eax,eax
jz cannot_move
mov [caret_line],eax
dec [caret_line_number]
clc
retn
cannot_move:
stc
retn
move_line_down:
mov esi,[caret_line]
find_next_line:
mov eax,[esi]
or eax,eax
jz cannot_move
btr eax,0
jnc down_ok
mov esi,eax
jmp find_next_line
down_ok:
mov [caret_line],eax
inc [caret_line_number]
clc
retn
move_page_up:
mov eax,[caret_line_number]
sub eax,[window_height]
ja pgup_caret_ok
mov eax,1
pgup_caret_ok:
call find_line
mov [caret_line],esi
mov [caret_line_number],ecx
mov eax,[window_line_number]
sub eax,[window_height]
ja pgup_window_ok
mov eax,1
cmp [window_line_number],eax
je moved_ok
pgup_window_ok:
call find_line
mov [window_line],esi
mov [window_line_number],ecx
retn
move_page_down:
mov eax,[caret_line_number]
add eax,[window_height]
call find_line
mov [caret_line],esi
mov [caret_line_number],ecx
mov eax,[window_line_number]
mov ecx,[window_height]
add eax,ecx
mov ebx,[lines_count]
sub ebx,ecx
jbe moved_ok
inc ebx
cmp eax,ebx
jb pgdn_window_ok
mov eax,ebx
cmp [window_line_number],eax
je moved_ok
pgdn_window_ok:
call find_line
mov [window_line],esi
mov [window_line_number],ecx
moved_ok:
retn
move_to_previous_word:
call get_caret_segment
mov ecx,[caret_position]
sub ecx,edx
cmp edx,SEGMENT_DATA_LENGTH
jbe find_word_to_the_left
mov edx,SEGMENT_DATA_LENGTH
find_word_to_the_left:
sub edx,1
jc word_in_previous_segment
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
call recognize_character
jnc find_word_start
jmp find_word_to_the_left
word_in_previous_segment:
mov eax,[esi+4]
or eax,eax
jz previous_word_ok
mov esi,eax
btr esi,0
jnc word_in_previous_line
mov edx,SEGMENT_DATA_LENGTH
sub ecx,edx
jmp find_word_to_the_left
word_in_previous_line:
mov [caret_line],esi
dec [caret_line_number]
mov edx,SEGMENT_DATA_LENGTH
xor ecx,ecx
find_last_segment:
test byte [esi],1
jz find_word_to_the_left
mov esi,[esi]
dec esi
add ecx,SEGMENT_DATA_LENGTH
jmp find_last_segment
find_word_start:
sub edx,1
jc word_on_segment_edge
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
call recognize_character
jc previous_word_ok
jmp find_word_start
word_on_segment_edge:
mov esi,[esi+4]
btr esi,0
jnc previous_word_ok
mov edx,SEGMENT_DATA_LENGTH
sub ecx,edx
jmp find_word_start
previous_word_ok:
add ecx,edx
inc ecx
mov [caret_position],ecx
retn
move_to_next_word:
mov ecx,[caret_position]
sub ecx,edx
find_word_end:
cmp edx,SEGMENT_DATA_LENGTH
jae word_wraps_segment_edge
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
call recognize_character
jc find_word_to_the_right
add edx,1
jmp find_word_end
word_wraps_segment_edge:
mov esi,[esi]
or esi,esi
jz move_to_line_end
btr esi,0
jnc word_in_next_line
add ecx,SEGMENT_DATA_LENGTH
sub edx,SEGMENT_DATA_LENGTH
jmp find_word_end
find_word_to_the_right:
cmp edx,SEGMENT_DATA_LENGTH
jae word_in_next_segment
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
call recognize_character
jnc next_word_ok
add edx,1
jmp find_word_to_the_right
word_in_next_segment:
mov esi,[esi]
or esi,esi
jz move_to_line_end
btr esi,0
jnc word_in_next_line
add ecx,SEGMENT_DATA_LENGTH
sub edx,SEGMENT_DATA_LENGTH
jmp find_word_to_the_right
word_in_next_line:
mov [caret_line],esi
inc [caret_line_number]
xor ecx,ecx
xor edx,edx
jmp find_word_to_the_right
next_word_ok:
add ecx,edx
mov [caret_position],ecx
retn
move_to_line_end:
mov esi,[caret_line]
mov eax,[esi+8]
mov [caret_position],eax
retn
get_word_at_caret:
call get_caret_segment
mov ebx,[caret_position]
sub ebx,edx
find_left_edge:
or edx,edx
jz left_edge_in_previous_segment
cmp edx,SEGMENT_DATA_LENGTH
ja left_edge_ok
mov al,[esi+SEGMENT_HEADER_LENGTH+edx-1]
call recognize_character
jc left_edge_ok
dec edx
jmp find_left_edge
left_edge_in_previous_segment:
mov esi,[esi+4]
btr esi,0
jnc left_edge_ok
mov edx,SEGMENT_DATA_LENGTH
sub ebx,edx
jmp find_left_edge
left_edge_ok:
add ebx,edx
call get_caret_segment
mov ecx,[caret_position]
sub ecx,edx
find_right_edge:
cmp edx,SEGMENT_DATA_LENGTH
jae right_edge_in_next_segment
mov al,[esi+SEGMENT_HEADER_LENGTH+edx]
call recognize_character
jc right_edge_ok
inc edx
jmp find_right_edge
right_edge_in_next_segment:
mov esi,[esi]
btr esi,0
jnc right_edge_ok
xor edx,edx
add ecx,SEGMENT_DATA_LENGTH
jmp find_right_edge
right_edge_ok:
add ecx,edx
sub ecx,ebx
mov edx,ebx
retn