512 lines
9.9 KiB
PHP
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
|