; flat editor core ; Copyright (c) 1999-2015, Tomasz Grysztar. ; All rights reserved. insert_block: test [editor_mode],FEMODE_VERTICALSEL jz block_to_insert_ok push esi or edx,-1 xor ecx,ecx count_line_characters: lodsb cmp al,9 je cannot_insert cmp al,0Dh je count_next_line or al,al jz at_end_of_line inc ecx jmp count_line_characters at_end_of_line: dec esi jmp check_block_width count_next_line: lodsb cmp al,0Ah je check_block_width dec esi check_block_width: cmp edx,-1 je line_to_insert_ok cmp edx,ecx je line_to_insert_ok cannot_insert: pop esi stc retn line_to_insert_ok: mov edx,ecx xor ecx,ecx cmp byte [esi],0 jne count_line_characters pop esi block_to_insert_ok: mov eax,[caret_line] mov ecx,[caret_line_number] mov edx,[caret_position] mov [selection_line],eax mov [selection_line_number],ecx mov [selection_position],edx mov ebx,esi get_line_to_insert: lodsb or al,al jz insert_full_line cmp al,0Dh je insert_full_line cmp al,0Ah je insert_full_line cmp al,9 jne get_line_to_insert push esi dec esi mov ecx,esi sub ecx,ebx mov esi,ebx push ecx call insert_into_line pop ecx add [caret_position],ecx mov ecx,[caret_position] and ecx,not 111b sub ecx,[caret_position] add ecx,8 xor esi,esi push ecx call insert_into_line pop ecx add [caret_position],ecx pop esi mov ebx,esi jmp get_line_to_insert insert_full_line: dec esi push esi mov ecx,esi sub ecx,ebx mov esi,ebx push ecx call insert_into_line pop ecx add [caret_position],ecx pop esi lodsb or al,al jz last_line_inserted cmp al,0Ah je lf_first lodsb cmp al,0Ah je next_line_to_insert dec esi jmp next_line_to_insert lf_first: lodsb cmp al,0Dh je next_line_to_insert dec esi next_line_to_insert: mov ebx,[selection_position] test [editor_mode],FEMODE_VERTICALSEL jnz insert_in_next_line test [editor_mode],FEMODE_OVERWRITE jz insert_new_line push esi call clear_rest_of_line pop esi xor ebx,ebx insert_in_next_line: push esi ebx mov esi,[caret_line] call check_line_length pop ebx call go_to_next_line pop esi mov ebx,esi jmp get_line_to_insert last_line_inserted: mov esi,[caret_line] call check_line_length clc retn insert_new_line: push esi push [caret_line] push [caret_line_number] xor ebx,ebx call break_line pop [caret_line_number] pop ebx esi push [caret_line] mov [caret_line],ebx go_to_end_of_first_line: test byte [ebx],1 jz insert_full_lines mov ebx,[ebx] dec ebx jmp go_to_end_of_first_line insert_full_lines: call allocate_segment jc memory_shortage call store_allocated_segment_for_undo mov [ebx],eax mov ebx,eax mov eax,[caret_line] mov [ebx+4],eax mov [caret_line],ebx inc [caret_line_number] inc [lines_count] call set_line jc full_lines_inserted jmp insert_full_lines full_lines_inserted: pop edi mov eax,[caret_line] mov [edi+4],eax mov [ebx],edi call cut_line_break mov esi,[caret_line] call check_line_length clc retn set_line: mov edi,ebx add edi,SEGMENT_HEADER_LENGTH mov ecx,SEGMENT_DATA_LENGTH mov [caret_position],0 push ebx copy_line: lodsb or al,al jz last_line_set cmp al,0Ah je copy_lf cmp al,0Dh je copy_cr cmp al,9 je copy_tab set_character: stosb loop copy_line extra_segment: call allocate_segment jc memory_shortage call store_allocated_segment_for_undo mov edi,eax or eax,1 mov [ebx],eax or ebx,1 mov [edi+4],ebx mov ebx,edi add edi,SEGMENT_HEADER_LENGTH mov ecx,SEGMENT_DATA_LENGTH add [caret_position],ecx jmp copy_line copy_tab: mov al,20h mov edx,SEGMENT_DATA_LENGTH sub edx,ecx add edx,[caret_position] and edx,111b cmp edx,111b je set_character dec esi jmp set_character copy_lf: cmp byte [esi],0Dh jne copy_new_line inc esi jmp copy_new_line copy_cr: cmp byte [esi],0Ah jne copy_new_line inc esi copy_new_line: pop edx call finish_line clc retn last_line_set: pop edx call finish_line stc retn finish_line: mov eax,SEGMENT_DATA_LENGTH sub eax,ecx add eax,[caret_position] mov [caret_position],eax mov [edx+8],eax call register_length mov al,20h rep stosb retn delete_block: test [editor_mode],FEMODE_VERTICALSEL jnz delete_vertical_block mov eax,[caret_line_number] cmp eax,[selection_line_number] je delete_vertical_block mov esi,[caret_line] mov ecx,[caret_line_number] mov edx,[caret_position] cmp ecx,[selection_line_number] jbe position_for_deleting_ok xchg esi,[selection_line] xchg ecx,[selection_line_number] xchg edx,[selection_position] mov [caret_line],esi mov [caret_line_number],ecx mov [caret_position],edx position_for_deleting_ok: test [editor_mode],FEMODE_OVERWRITE jnz clear_block call get_caret_segment cmp edx,SEGMENT_DATA_LENGTH jb first_line_of_block call attach_empty_segments first_line_of_block: mov ecx,[caret_position] sub ecx,edx skip_rest_of_first_line: add ecx,SEGMENT_DATA_LENGTH mov eax,[esi] btr eax,0 jnc end_of_first_line mov esi,eax jmp skip_rest_of_first_line end_of_first_line: call store_segment_for_undo mov edi,esi mov esi,eax remove_middle_lines: cmp esi,[selection_line] je middle_lines_removed call store_freed_segment_for_undo mov ebx,[esi] call cancel_line mov esi,ebx btr esi,0 jnc remove_middle_lines remove_middle_line_segments: call store_freed_segment_for_undo mov esi,[esi] btr esi,0 jc remove_middle_line_segments jmp remove_middle_lines middle_lines_removed: call store_segment_for_undo mov eax,esi or eax,1 mov [edi],eax mov eax,edi or eax,1 mov [esi+4],eax call cancel_line add ecx,[selection_position] sub ecx,[caret_position] call delete_from_line mov esi,[caret_line] find_following_line: mov esi,[esi] btr esi,0 jc find_following_line or esi,esi jz following_line_ok call store_segment_for_undo mov eax,[caret_line] mov [esi+4],eax following_line_ok: mov esi,[caret_line] call check_line_length block_deleted: retn clear_block: push [caret_line] push [caret_position] clear_lines: call clear_rest_of_line mov [caret_line],esi mov [caret_position],0 cmp esi,[selection_line] jne clear_lines mov ecx,[selection_position] call clear_in_line pop [caret_position] pop [caret_line] retn delete_vertical_block: push [caret_line] push [caret_line_number] mov eax,[caret_position] cmp eax,[selection_position] jbe delete_vertical_block_line xchg eax,[selection_position] mov [caret_position],eax delete_vertical_block_line: mov ecx,[selection_position] sub ecx,[caret_position] call delete_from_line mov esi,[caret_line] call check_line_length mov esi,[caret_line] mov eax,[caret_line_number] cmp eax,[selection_line_number] je vertical_block_deleted ja delete_in_previous_line delete_in_next_line: mov esi,[esi] btr esi,0 jc delete_in_next_line mov [caret_line],esi inc [caret_line_number] jmp delete_vertical_block_line delete_in_previous_line: mov esi,[esi+4] mov [caret_line],esi dec [caret_line_number] jmp delete_vertical_block_line vertical_block_deleted: pop [caret_line_number] pop [caret_line] mov [selection_line],0 retn get_block_length: test [editor_mode],FEMODE_VERTICALSEL jnz get_length_of_vertical_block mov esi,[caret_line] mov edx,[caret_position] mov ebx,[selection_line] mov ecx,[selection_position] mov eax,[caret_line_number] cmp eax,[selection_line_number] je get_length_of_vertical_block jb get_length_of_standard_block xchg esi,ebx xchg ecx,edx get_length_of_standard_block: push ecx mov ecx,[esi+8] sub ecx,edx jae add_length_of_line xor ecx,ecx add_length_of_line: add ecx,2 add [esp],ecx skip_standard_block_line: mov esi,[esi] btr esi,0 jc skip_standard_block_line cmp esi,ebx je length_of_block_ok mov ecx,[esi+8] jmp add_length_of_line length_of_block_ok: pop ecx retn get_length_of_vertical_block: mov edx,[caret_line_number] sub edx,[selection_line_number] jae vertical_dimension_ok neg edx vertical_dimension_ok: mov eax,[caret_position] sub eax,[selection_position] jae horizontal_dimension_ok neg eax horizontal_dimension_ok: mov ecx,eax add eax,2 mul edx add ecx,eax retn copy_block: test [editor_mode],FEMODE_VERTICALSEL jnz copy_vertical_block mov esi,[caret_line] mov edx,[caret_position] mov ebx,[selection_line] mov ecx,[selection_position] mov eax,[caret_line_number] cmp eax,[selection_line_number] je copy_vertical_block jb copy_standard_block xchg esi,ebx xchg ecx,edx copy_standard_block: push ecx push ebx mov ecx,[esi+8] sub ecx,edx jb after_line_end call copy_from_line jmp block_line_copied after_line_end: mov esi,[esi] btr esi,0 jc after_line_end block_line_copied: pop ebx copy_next_line: mov ax,0A0Dh stosw cmp esi,ebx je copy_from_last_line push ebx mov ecx,[esi+8] xor edx,edx call copy_from_line pop ebx jmp copy_next_line copy_from_last_line: pop ecx xor edx,edx call copy_from_line xor al,al stosb retn copy_vertical_block: mov esi,[caret_line] mov ebx,[selection_line] mov edx,[caret_position] mov ecx,[selection_position] mov eax,[caret_line_number] cmp eax,[selection_line_number] jbe vertical_block_starting_line_ok xchg esi,ebx vertical_block_starting_line_ok: cmp edx,ecx jbe vertical_block_starting_position_ok xchg edx,ecx vertical_block_starting_position_ok: sub ecx,edx copy_line_from_vertical_block: mov eax,ebx sub eax,esi push eax ebx ecx edx call copy_from_line pop edx ecx ebx eax or eax,eax jz vertical_block_copied mov ax,0A0Dh stosw jmp copy_line_from_vertical_block vertical_block_copied: xor al,al stosb retn copy_from_line: mov ebx,ecx find_copying_origin: cmp edx,SEGMENT_DATA_LENGTH jb copy_line_segment mov esi,[esi] btr esi,0 jnc line_data_ended sub edx,SEGMENT_DATA_LENGTH jmp find_copying_origin copy_line_segment: mov ecx,SEGMENT_DATA_LENGTH sub ecx,edx cmp ebx,ecx jae line_segment_length_ok mov ecx,ebx line_segment_length_ok: sub ebx,ecx mov eax,[esi] lea esi,[esi+SEGMENT_HEADER_LENGTH+edx] rep movsb mov esi,eax btr esi,0 jnc line_data_ended xor edx,edx jmp copy_line_segment line_data_ended: or ebx,ebx jz line_copy_done mov ecx,ebx mov al,20h rep stosb line_copy_done: retn