virtual at 0 editor_data: .hPlugin dd ? .hFile dd ? if (.hPlugin <> viewer_data.hPlugin) | (.hFile <> viewer_data.hFile) error in viewer_IsHandleUsed/editor_IsHandleUsed end if .memsize dd ? .encoding db ? .flags db ? ; & 0x80: modified ; & 0x40: file is locked ; & 0x20: next key as a symbol ; & 0x10: replace mode (vs insert) .eol db ? rb 1 .first_block dd ? .last_block dd ? .numfree dd ? .freeblocks dd ? .numlines dd ? .curline dd ? .curcol dd ? ;.curpos_block dd ? ;.curpos_offs dd ? .cur_block dd ? .cur_offs dd ? .cur_delta dd ? .cursor_x dd ? .cursor_y dd ? align 200h .filename rb 1024 .hostname rb 1024 if (.filename <> viewer_data.filename) | (.hostname <> viewer_data.hostname) error in viewer_getname/editor_getname end if .buf rb 16384 ; all I/O operations use this buffer .basesize = $ .linedata_start: end virtual virtual at 0 editor_line: .block dd ? .offs dw ? ;.length dd ? .plugdata: end virtual ; when a file is loaded into the editor, this file is fragmented to blocks ; each block has RESERVE_IN_BLOCK empty bytes to allow quick inserting ; must be dword-aligned! edit.RESERVE_IN_BLOCK = 16 edit.eol_dos = 1 ; DOS/Win EOLn style (0D 0A) edit.eol_unix = 2 ; Unix EOLn style (0A) edit.eol_mac = 3 ; MacOS EOLn style (0D) virtual at 0 edit_block_header: .next dd ? .prev dd ? .limit dd ? .size = $ ; must be dword-aligned end virtual edit_file: mov eax, [ebp + panel1_files - panel1_data] mov ecx, [eax+ecx*4] test byte [ecx], 10h jz .file ret .file: ; calculate required memory size cmp dword [ecx+36], 0 jnz .nomemory ; block size = 4096 ; block header: edit_block_header.size bytes ; some plugin-specific data can follow ; reserve RESERVE_IN_BLOCK free bytes in the end of block mov ebx, 4096 mov eax, [EditPlugInfo] add eax, edit_block_header.size mov [EditBlockStart], eax sub ebx, eax sub ebx, edit.RESERVE_IN_BLOCK mov [EditBlockSize], ebx ; now ebx = size of file data in each block mov eax, [ecx+32] ; if eax == 0, set eax = 1 sub eax, 1 adc eax, 1 xor edx, edx div ebx sub edx, 1 sbb eax, -1 add eax, [EditDataSize] ; eax = number of blocks + memory for editor_data structure cmp eax, 0x80000000 shr 12 jb .memok .nomemory: push aEditNoMemory mov eax, esp push ContinueBtn push 1 push eax push 1 call SayErr pop eax ret .memok: lea esi, [ebp + panel1_dir - panel1_data] push eax push ecx mov ecx, eax shl ecx, 12 mov edx, editor_vtable call new_screen pop ecx pop ebx test eax, eax jnz @f ret @@: mov [ebp + editor_data.memsize], ebx mov al, [EditEOLStyle] mov [ebp + editor_data.eol], al mov eax, [esi + panel1_hPlugin - panel1_data] mov [ebp + editor_data.hPlugin], eax test eax, eax jz .nocopyhostname lea edi, [ebp + editor_data.hostname] push esi mov eax, dword [esi + panel1_parents - panel1_dir] mov esi, dword [esi + panel1_parents_sz - panel1_dir] add esi, eax @@: dec esi cmp byte [esi-1], 0 jz @f cmp byte [esi-1], '/' jnz @b @@: lodsb stosb test al, al jnz @b pop esi .nocopyhostname: mov eax, dword [esi + panel1_hFile - panel1_dir] mov [ebp + editor_data.hFile], eax mov [ebp + editor_data.encoding], encodings.cp866 xor eax, eax mov [ebp + editor_data.flags], al inc eax mov [ebp + editor_data.numlines], eax lea edi, [ebp + editor_data.filename] mov ebx, readinfo mov [ebx+21], edi @@: lodsb test al, al jz @f stosb jmp @b @@: lea esi, [ecx+40] mov al, '/' cmp byte [edi-1], al jz @f stosb @@: lodsb stosb test al, al jnz @b ; load file into memory mov esi, [ebp + editor_data.memsize] mov edi, [EditDataSize] sub esi, edi ; esi = number of blocks shl edi, 12 ;mov [ebp + editor_data.curpos_block], edi mov [ebp + editor_data.first_block], edi mov [ebp + editor_data.cur_block], edi add edi, ebp ; edi -> first block mov [ebp + editor_data.linedata_start + editor_line.block], edi xor eax, eax mov [ebx+4], eax mov [ebx+8], eax mov dword [ebx+12], 16384 lea eax, [ebp + editor_data.buf] mov [ebx+16], eax mov edx, [ebp + editor_data.hPlugin] test edx, edx jz @f pushad push O_READ push dword [ebx+21] push [ebp + editor_data.hFile] call [edx + PluginInfo.open] popad test eax, eax jz ..openerr_in_screen mov ebx, eax @@: .readloop: mov edx, [ebp + editor_data.hPlugin] test edx, edx jz .readnative pushad push 16384 push [readinfo.data] push ebx call [edx + PluginInfo.read] popad cmp eax, -1 jnz .readok ; let us hope that plugin says error itself push ebp push ebx call [edx + PluginInfo.close] pop ebp jmp .readfailed .readnative: push ebx push 70 pop eax int 40h mov edx, ebx xchg eax, edx pop ebx add dword [ebx+4], eax adc dword [ebx+8], 0 test edx, edx jz .readok cmp edx, 6 jz .readok push dword [ebx+21] push aCannotReadFile xchg eax, edx call get_error_msg push eax mov eax, esp push RetryOrCancelBtn push 2 push eax push 3 call SayErr add esp, 3*4 test eax, eax jz .readnative .readfailed: jmp delete_active_screen .readok: ; eax = number of bytes read test eax, eax jnz @f mov ecx, edi sub ecx, ebp cmp ecx, [ebp + editor_data.first_block] jnz .readdone @@: push eax ebx mov ebx, [ebx+16] .loadloop: mov ecx, [EditBlockSize] cmp eax, ecx ja @f mov ecx, eax @@: sub eax, ecx push eax dec esi jns .hasblock push ecx add [ebp + editor_data.memsize], 8 add esi, 8 mov ecx, [ebp + editor_data.memsize] cmp ecx, 80000000h shr 12 jb @f .nomemory2: pop ecx eax ebx eax call .nomemory jmp .readfailed @@: sub edi, ebp shl ecx, 12 mov edx, ebp call xpgrealloc test eax, eax jz .nomemory2 mov ebp, eax add edi, eax pop ecx .hasblock: lea eax, [edi + 0x1000] push eax sub eax, ebp stosd ; edit_block_header.next sub eax, 0x2000 stosd ; edit_block_header.prev mov eax, [EditBlockStart] add eax, ecx stosd ; edit_block_header.limit push ecx mov ecx, [EditPlugInfo] inc ecx jz @f dec ecx @@: xor eax, eax rep stosb ; info for plugins: zeroed pop ecx push esi edi ecx mov esi, ebx add ecx, 3 shr ecx, 2 rep movsd mov ebx, esi pop ecx edi ; calculate number of lines in this block mov esi, edi xor edx, edx test ecx, ecx jz .4 .1: lodsb cmp al, 13 jz @f cmp al, 10 jz @f mov dl, 0 jmp .3 @@: cmp al, dl mov dl, 0 jz .3 inc [ebp + editor_data.numlines] cmp al, 10 jz .3 mov dl, 10 .3: loop .1 .4: pop esi pop edi pop eax test eax, eax jnz .loadloop pop ebx eax cmp eax, 16384 jz .readloop .readdone: xor eax, eax mov ecx, edi sub ecx, ebp mov edx, ecx shr ecx, 12 sub ecx, [ebp + editor_data.memsize] neg ecx mov [ebp + editor_data.numfree], ecx jz .nofree mov [ebp + editor_data.freeblocks], edx push edi .addfree: add edx, 1000h mov [edi], edx add edi, 1000h loop .addfree mov [edi-1000h], eax pop edi .nofree: sub edi, 1000h mov [edi + edit_block_header.next], eax sub edi, ebp mov [ebp + editor_data.last_block], edi mov ecx, [EditDataSize] shl ecx, 12 mov [ecx + ebp + edit_block_header.prev], eax mov [ebp + editor_data.curline], eax mov [ebp + editor_data.curcol], eax mov [ebp + editor_data.cursor_x], eax inc eax mov [ebp + editor_data.cursor_y], eax mov eax, [EditBlockStart] ;mov [ebp + editor_data.curpos_offs], eax mov [ebp + editor_data.linedata_start + editor_line.offs], ax mov [ebp + editor_data.cur_offs], eax mov ecx, [ebp + editor_data.first_block] cmp [ecx + edit_block_header.limit], eax setz cl movzx ecx, cl dec ecx mov [ebp + editor_data.cur_delta], ecx call editor_init_lines editor_OnRedraw: mov eax, [ebp + editor_data.cursor_x] mov [cursor_x], eax mov eax, [ebp + editor_data.cursor_y] mov [cursor_y], eax test [ebp + editor_data.flags], 10h jz @f mov [cursor_size], cursor_big_size @@: call editor_test_cursor_x call editor_test_cursor_y call editor_set_keybar call editor_draw_text ret editor_save: cmp [ebp + editor_data.hPlugin], 0 jz .native push aCannotSaveToPlugin mov eax, esp push ContinueBtn push 1 push eax push 1 call SayErr pop eax ret .native: call editor_calc_filesize mov ebx, writeinfo mov [ebx+4], eax xor eax, eax mov [ebx+8], eax mov [ebx+12], eax mov [ebx+16], eax lea eax, [ebp + editor_data.filename] mov [ebx+21], eax .setsize_retry: mov byte [ebx], 4 push 70 pop eax push ebx int 0x40 pop ebx mov byte [ebx], 3 test eax, eax jz .sizeok push dword [ebx+21] push aCannotWriteFile call get_error_msg push eax mov eax, esp push RetryOrCancelBtn push 2 push eax push 3 call SayErr add esp, 12 test eax, eax jz .setsize_retry .ret: ret .sizeok: and dword [ebx+4], 0 mov esi, [ebp + editor_data.first_block] add esi, ebp mov ebx, [EditBlockStart] call editor_normalize_offs jnc .writeok lea edi, [ebp + editor_data.buf] .loop: mov ecx, 16384 call editor_get_data test eax, eax jz .done push ebx mov ebx, writeinfo mov [ebx+12], eax mov [ebx+16], edi .write_retry: push 70 pop eax push ebx int 0x40 pop ebx test eax, eax jz .writeok push dword [ebx+21] push aCannotWriteFile call get_error_msg push eax mov eax, esp push RetryOrCancelBtn push 2 push eax push 3 call SayErr add esp, 12 test eax, eax jz .write_retry ret .writeok: mov eax, [ebx+12] add [ebx+4], eax adc dword [ebx+8], 0 pop ebx jmp .loop .done: and [ebp + editor_data.flags], not 0x80 ret editor_calc_filesize: xor eax, eax push esi mov esi, [ebp + editor_data.first_block] @@: add esi, ebp add eax, [esi + edit_block_header.limit] sub eax, [EditBlockStart] mov esi, [esi + edit_block_header.next] test esi, esi jnz @b pop ebx ret editor_get_data: push edi test esi, esi jz .ret .loop: mov edx, [esi + edit_block_header.limit] sub edx, ebx push ecx cmp ecx, edx jb @f mov ecx, edx @@: push esi add esi, ebx add ebx, ecx add eax, ecx rep movsb pop esi pop ecx sub ecx, edx jb .ret mov esi, [esi + edit_block_header.next] mov ebx, [EditBlockStart] test esi, esi jz .ret add esi, ebp jmp .loop .ret: mov eax, edi pop edi sub eax, edi ret editor_get_pos: ;mov esi, [ebp + editor_data.curpos_block] ;mov ebx, [ebp + editor_data.curpos_offs] mov esi, [ebp + editor_data.linedata_start + editor_line.block] sub esi, ebp movzx ebx, [ebp + editor_data.linedata_start + editor_line.offs] @@: test esi, esi jz @f add esi, ebp cmp ebx, [esi + edit_block_header.limit] jb @f mov esi, [esi + edit_block_header.next] mov ebx, [EditBlockStart] jmp @b @@: ret editor_curline_start: mov edx, [EditPlugInfo] add edx, editor_line.plugdata mov eax, [ebp + editor_data.cursor_y] dec eax imul eax, edx lea edi, [ebp + eax + editor_data.linedata_start] mov esi, [edi + editor_line.block] movzx ebx, [edi + editor_line.offs] ret editor_step_forward: ; in: esi = block (must be nonzero), ebx = offset in block ; out: esi = block (zero iff EOF reached), ebx = offset in block ; out: CF=1 iff EOF NOT reached inc ebx editor_normalize_offs: cmp ebx, [esi + edit_block_header.limit] jb @f mov esi, [esi + edit_block_header.next] mov ebx, [EditBlockStart] test esi, esi jz @f add esi, ebp stc @@: ret editor_step_backward: ; in: esi = block (must be nonzero), ebx = offset in block ; out: esi = block (zero iff input was at the beginning), ebx = offset in block ; out: CF=1 iff start of file reached dec ebx cmp ebx, [EditBlockStart] jae @f mov esi, [esi + edit_block_header.prev] test esi, esi stc jz @f add esi, ebp mov ebx, [esi + edit_block_header.limit] dec ebx @@: ret editor_get_string: ; read string up to the end of line ; in: esi = block, ebx = offset in block ; in: edi = destination, ecx = maximum number of bytes to copy, edx = number of bytes to skip ; out: esi = block, ebx = offset in block ; out: ecx = number of rest bytes (ecx_in - ecx_out = number of copied characters) mov ah, [edit_normal_color] cmp ebx, [esi + edit_block_header.limit] jz .retnp push 0 ; current position in line .loop: test ecx, ecx jz .ret mov al, [esi + ebx] cmp al, 13 jz .ret cmp al, 10 jz .ret cmp al, 9 jz .tab inc dword [esp] dec edx jns .4 xor edx, edx stosw dec ecx .4: call editor_step_forward jc .loop .ret: pop edx .retnp: ret .tab: push eax edx mov eax, [esp+8] xor edx, edx div [editor_tabsize] sub edx, [editor_tabsize] neg edx add [esp+8], edx sub [esp], edx pop edx eax jns .4 mov al, ' ' @@: stosw dec ecx jz .ret inc edx jnz @b jmp .4 editor_find_newline: ; in: esi = block, ebx = offset in block ; out: esi = block, ebx = offset in block, ecx = line length xor ecx, ecx test esi, esi jz .ret0 cmp ebx, [esi + edit_block_header.limit] jb .1 xor esi, esi .ret0: ret .1: mov al, [esi + ebx] inc ecx call editor_step_forward cmp al, 13 jz .2 cmp al, 10 jz .2 test esi, esi jnz .1 .ret1: mov esi, [ebp + editor_data.last_block] add esi, ebp mov ebx, [esi + edit_block_header.limit] ret .2: dec ecx test esi, esi jz .ret1 cmp al, 13 jnz .ret cmp byte [esi + ebx], 10 jnz .ret call editor_step_forward jnc .ret1 .ret: ret editor_prev_newline: xor ecx, ecx test esi, esi jnz @f mov esi, [ebp + editor_data.last_block] add esi, ebp mov ebx, [esi + edit_block_header.limit] @@: call editor_step_backward jc .ret mov al, [esi + ebx] call editor_step_backward jc .ret cmp al, 10 jnz .1 cmp byte [esi + ebx], 13 jnz .1 @@: call editor_step_backward jc .ret .1: inc ecx mov al, [esi + ebx] cmp al, 13 jz @f cmp al, 10 jnz @b @@: dec ecx inc ebx cmp ebx, [esi + edit_block_header.limit] jb .ret mov esi, [esi + edit_block_header.next] mov ebx, [EditBlockStart] test esi, esi jz .ret add esi, ebp .ret: test esi, esi jnz @f mov esi, [ebp + editor_data.first_block] mov ebx, [EditBlockStart] add esi, ebp @@: ret editor_init_lines: call editor_get_pos test esi, esi jnz @f mov esi, [ebp + editor_data.last_block] add esi, ebp mov ebx, [esi + edit_block_header.limit] @@: mov ecx, max_height lea edi, [ebp + editor_data.linedata_start] .1: mov eax, esi stosd ; editor_line.block mov eax, ebx stosw ; editor_line.offs push ecx call editor_find_newline ;mov eax, ecx ;stosd ; editor_line.length xor eax, eax mov ecx, [EditPlugInfo] rep stosb pop ecx loop .1 ret editor_draw_status: lea edi, [ebp + editor_data.buf] mov ah, [edit_status_color] mov ecx, [cur_width] sub ecx, 56 cmp ecx, 25 jge @f push 25 pop ecx @@: call viewedit_draw_filename inc ecx rep stosw test [ebp + editor_data.flags], 80h jz @f mov al, '*' @@: stosw mov al, ' ' test [ebp + editor_data.flags], 40h jz @f mov al, '-' @@: stosw mov al, ' ' test [ebp + editor_data.flags], 20h jz @f mov al, '"' @@: stosw mov al, ' ' mov cl, 10 rep stosw movzx esi, [ebp+editor_data.encoding] lea esi, [encodings.names+esi*8] push edi esi dec edi dec edi std add esi, 8 @@: dec esi cmp byte [esi], ' ' jz @b @@: lodsb stosw cmp esi, [esp] jae @b cld pop esi edi mov esi, aLine mov cl, 8 @@: lodsb stosw loop @b mov cl, 13 mov al, ' ' rep stosw std push edi dec edi dec edi push eax mov eax, [ebp + editor_data.numlines] mov cl, 10 @@: xor edx, edx div ecx xchg eax, edx add al, '0' mov ah, [edit_status_color] stosw xchg eax, edx test eax, eax jnz @b mov al, '/' mov ah, [edit_status_color] stosw mov eax, [ebp + editor_data.curline] add eax, [ebp + editor_data.cursor_y] @@: xor edx, edx div ecx xchg eax, edx add al, '0' mov ah, [edit_status_color] stosw xchg eax, edx test eax, eax jnz @b pop eax stosw cld pop edi mov ah, [edit_status_color] mov esi, aCol mov cl, 7 @@: lodsb stosw loop @b mov eax, [ebp + editor_data.curcol] add eax, [ebp + editor_data.cursor_x] inc eax mov cl, 10 push -'0' @@: xor edx, edx div ecx push edx test eax, eax jnz @b @@: pop eax mov ah, [edit_status_color] add al, '0' jz @f stosw jmp @b @@: mov al, ' ' mov cl, 13 rep stosw xor eax, eax xor edx, edx call get_console_ptr lea esi, [ebp + editor_data.buf] mov ecx, [cur_width] shr ecx, 1 rep movsd adc ecx, ecx rep movsw cmp [ebp + editor_data.cur_delta], -1 jnz .a mov al, ' ' mov byte [edi-4*2], al mov byte [edi-3*2], al mov byte [edi-2*2], al mov byte [edi-1*2], al mov eax, [ebp + editor_data.cur_block] add eax, ebp add eax, [ebp + editor_data.cur_offs] movzx eax, byte [eax] mov cl, 100 ;xor edx, edx ; edx=0 already div ecx test al, al jz @f add al, '0' mov [edi-3*2], al @@: xchg eax, edx aam test ah, ah jnz .b cmp byte [edi-3*2], ' ' jz @f .b: add ah, '0' mov [edi-2*2], ah @@: add al, '0' mov [edi-1*2], al .a: ret editor_draw_line: push ecx mov ecx, [cur_width] test esi, esi jz .2 lea edi, [ebp + editor_data.buf] push edx edi mov edx, [ebp + editor_data.curcol] call editor_get_string mov al, ' ' rep stosw pop esi edx xor eax, eax call get_console_ptr mov ecx, [cur_width] shr ecx, 1 rep movsd adc ecx, ecx rep movsw pop ecx ret .2: xor eax, eax call get_console_ptr mov al, ' ' mov ah, [edit_normal_color] rep stosw pop ecx ret editor_draw_text: call editor_draw_status push 1 pop edx lea ecx, [ebp + editor_data.linedata_start] .1: mov esi, [ecx + editor_line.block] movzx ebx, [ecx + editor_line.offs] add ecx, editor_line.plugdata add ecx, [EditPlugInfo] call editor_draw_line inc edx mov eax, [cur_height] dec eax cmp edx, eax jb .1 jmp draw_image editor_set_keybar: mov eax, keybar_editor movzx esi, [ebp+editor_data.encoding] dec esi jz @f push 1 pop esi @@: lea esi, [encodings.names+esi*8] lea edi, [eax+keybar_cp2-keybar_editor] movsd movsw jmp draw_keybar editor_up_scroll: push ecx sub [ebp + editor_data.curline], ecx mov edx, [EditPlugInfo] add edx, editor_line.plugdata imul eax, edx, max_height imul ecx, edx sub ecx, eax neg ecx lea esi, [ebp + ecx + editor_data.linedata_start - 4] lea edi, [ebp + eax + editor_data.linedata_start - 4] shr ecx, 2 std rep movsd cld jnc @f mov cx, [esi+2] mov [edi+2], cx sub edi, 2 @@: pop ecx add edi, 4 movzx ebx, [edi + editor_line.offs] mov esi, [edi + editor_line.block] @@: push ecx call editor_prev_newline sub edi, edx push edi mov eax, esi stosd ; editor_line.offs mov eax, ebx stosw ; editor_line.block ;mov eax, ecx ;stosd ; editor_line.length mov ecx, [EditPlugInfo] xor eax, eax rep stosb pop edi pop ecx loop @b ; fall through to editor_update_cur editor_update_cur: mov ecx, [ebp + editor_data.cursor_x] add ecx, [ebp + editor_data.curcol] call editor_curline_start xor edx, edx ; current position in the line cmp ebx, [esi + edit_block_header.limit] jz .notfound .scan: mov al, [esi+ebx] cmp al, 13 jz .notfound cmp al, 10 jz .notfound test ecx, ecx jz .found cmp al, 9 jz .tab inc edx dec ecx call editor_step_forward jc .scan .notfound: test esi, esi jnz @f mov esi, [ebp + editor_data.last_block] add esi, ebp mov ebx, [esi + edit_block_header.limit] @@: mov [ebp + editor_data.cur_delta], ecx xor eax, eax jmp .reta .found: xor eax, eax .founda: or [ebp + editor_data.cur_delta], -1 .reta: sub esi, ebp mov [ebp + editor_data.cur_block], esi mov [ebp + editor_data.cur_offs], ebx ret .tab: push edx mov eax, edx xor edx, edx div [editor_tabsize] sub edx, [editor_tabsize] neg edx add [esp], edx cmp ecx, edx jb .curintab sub ecx, edx pop edx call editor_step_forward jnc .notfound test ecx, ecx jz .found jmp .scan .curintab: sub [esp], edx pop edx cmp edx, [ebp + editor_data.curcol] setc al jae @f mov [ebp + editor_data.curcol], edx @@: sub edx, [ebp + editor_data.curcol] mov [ebp + editor_data.cursor_x], edx mov [cursor_x], edx jmp .founda editor_down_scroll: push ecx lea edi, [ebp + editor_data.linedata_start] mov edx, [EditPlugInfo] add edx, editor_line.plugdata imul ecx, edx lea esi, [edi + ecx] imul eax, edx, max_height sub eax, ecx mov ecx, eax shr ecx, 2 rep movsd adc ecx, ecx rep movsw @@: mov esi, edi sub esi, edx movzx ebx, [esi + editor_line.offs] mov esi, [esi + editor_line.block] pop ecx jecxz .ret @@: push ecx call editor_find_newline mov eax, esi stosd ; editor_line.block mov eax, ebx stosw ; editor_line.offs ;mov eax, ecx ;stosd ; editor_line.length mov ecx, [EditPlugInfo] xor eax, eax rep stosb pop ecx loop @b .ret: ret editor_end_scroll: call editor_curline_start ; calculate visible length of the line (it differs from the real length if tabulations are present) xor ecx, ecx cmp ebx, [esi + edit_block_header.limit] jz .calcdone .calcloop: mov al, [esi+ebx] cmp al, 10 jz .calcdone cmp al, 13 jz .calcdone cmp al, 9 jz .calctab inc ecx .calcnext: call editor_step_forward jc .calcloop jmp .calcdone .calctab: mov eax, ecx xor edx, edx div [editor_tabsize] sub edx, [editor_tabsize] sub ecx, edx jmp .calcnext .calcdone: test esi, esi jnz @f mov esi, [ebp + editor_data.last_block] add esi, ebp mov ebx, [esi + edit_block_header.limit] @@: sub esi, ebp mov [ebp + editor_data.cur_block], esi mov [ebp + editor_data.cur_offs], ebx and [ebp + editor_data.cur_delta], 0 ; ecx = number of symbols in the line ; calculate new position of view range mov eax, [ebp + editor_data.curcol] cmp ecx, eax jb .toleft add eax, [cur_width] cmp ecx, eax jae .toright sub ecx, [ebp + editor_data.curcol] mov [ebp + editor_data.cursor_x], ecx mov [cursor_x], ecx ret .toleft: mov [ebp + editor_data.curcol], ecx and [ebp + editor_data.cursor_x], 0 and [cursor_x], 0 stc ret .toright: mov eax, [cur_width] dec eax sub ecx, eax mov [ebp + editor_data.curcol], ecx mov [ebp + editor_data.cursor_x], eax mov [cursor_x], eax stc ret editor_move_linestart: ; in: esi = block, ebx = start offset, ecx = delta lea edi, [ebp + editor_data.linedata_start] mov edx, max_height .0: cmp [edi + editor_line.block], esi jnz .1 movzx eax, [edi + editor_line.offs] cmp eax, ebx ja .2 ; push eax ; add eax, [edi + editor_line.length] ; cmp eax, ebx ; jb @f ; add [edi + editor_line.length], ecx ;@@: ; pop eax cmp eax, [esi + edit_block_header.limit] jb .1 push esi ebx mov ebx, eax jmp .3 .2: push esi ebx mov ebx, eax add ebx, ecx .3: cmp ebx, [esi + edit_block_header.limit] jb .4 cmp [esi + edit_block_header.next], 0 jz .4 sub ebx, [esi + edit_block_header.limit] mov esi, [esi + edit_block_header.next] add esi, ebp add ebx, [EditBlockStart] jmp .3 .4: mov [edi + editor_line.block], esi mov [edi + editor_line.offs], bx pop ebx esi .1: add edi, editor_line.plugdata add edi, [EditPlugInfo] dec edx jnz .0 ;lea edx, [ebp + editor_data.curpos_block] ;call .5 ;add edx, editor_data.cur_block - editor_data.curpos_block lea edx, [ebp + editor_data.cur_block] ; call .5 ; ret .5: mov eax, [edx] add eax, ebp cmp eax, esi jnz .6 cmp [edx+4], ebx jbe @f add [edx+4], ecx @@: mov eax, [edx+4] sub eax, [esi + edit_block_header.limit] jb .6 push ecx mov ecx, [esi + edit_block_header.next] add ecx, ebp add eax, [EditBlockStart] mov [edx], ecx mov [edx+4], eax pop ecx .6: ret editor_reserve_symbol: push 1 pop ecx editor_reserve_space: ; Вставляет пустое место внутрь цепочки блоков ; in: ecx = number of symbols to add, esi = block, ebx = offset mov eax, [esi + edit_block_header.limit] add eax, ecx cmp eax, 4096 ja .add mov [esi + edit_block_header.limit], eax push esi ecx sub eax, ecx lea esi, [esi + eax - 1] lea edi, [esi + ecx] sub eax, ebx mov ecx, eax std rep movsb cld pop ecx esi call editor_move_linestart clc ret .add: push ecx mov eax, [esi + edit_block_header.limit] sub eax, [EditBlockStart] add eax, ecx push eax xor edx, edx div [EditBlockSize] push eax sub eax, [ebp + editor_data.numfree] jbe .norealloc mov edx, [ebp + editor_data.memsize] push eax edx add eax, edx mov ecx, eax shl ecx, 12 mov edx, ebp call xpgrealloc pop edx ecx test eax, eax jz .nomem add [ebp + editor_data.memsize], ecx sub eax, ebp add ebp, eax add esi, eax push ecx mov ecx, max_height lea edi, [ebp + editor_data.linedata_start] @@: add [edi + editor_line.block], eax add edi, editor_line.plugdata add edi, [EditPlugInfo] loop @b pop ecx shl edx, 12 add [ebp + editor_data.numfree], ecx lea edi, [edx + ebp] mov eax, [ebp + editor_data.freeblocks] mov [ebp + editor_data.freeblocks], edx @@: add edx, 1000h mov [edi], edx add edi, 1000h loop @b mov [edi-1000h], eax .norealloc: pop edx push [esi + edit_block_header.next] push esi sub [ebp + editor_data.numfree], edx mov edi, [ebp + editor_data.freeblocks] @@: mov [esi + edit_block_header.next], edi add edi, ebp push edi push dword [edi] stosd ; edit_block_header.next - will be filled later mov eax, esi sub eax, ebp stosd ; edit_block_header.prev mov eax, 4096 - edit.RESERVE_IN_BLOCK stosd ; edit_block_header.limit mov eax, [EditBlockSize] sub [esp+16], eax xor eax, eax mov ecx, [EditPlugInfo] rep stosb pop edi pop esi dec edx jnz @b mov [ebp + editor_data.freeblocks], edi mov edi, esi pop esi pop [edi + edit_block_header.next] pop ecx add ecx, [EditBlockSize] mov edx, ecx shr edx, 1;2 mov eax, ecx sub eax, edx cmp eax, [EditBlockSize] jb @f mov eax, [EditBlockSize] mov edx, ecx sub edx, eax @@: add eax, [EditBlockStart] add edx, [EditBlockStart] mov ecx, [esi + edit_block_header.limit] mov [esi + edit_block_header.limit], eax mov [edi + edit_block_header.limit], edx sub ecx, ebx push ecx push esi edi ecx add esi, ecx add esi, ebx push edx sub edx, [EditBlockStart] cmp ecx, edx jb @f mov ecx, edx @@: pop edx sub [esp], ecx add edi, edx sub esi, ecx sub edi, ecx rep movsb pop ecx edi esi push esi edi lea edi, [esi + eax - 1] add esi, ebx lea esi, [esi + ecx - 1] std rep movsb cld pop edi esi pop ecx mov ecx, ebx sub ecx, eax jb @f push esi edi add esi, eax add edi, [EditBlockStart] rep movsb pop edi esi @@: push esi edi sub esi, ebp sub edi, ebp cmp [ebp + editor_data.last_block], esi jnz @f mov [ebp + editor_data.last_block], edi @@: pop edi esi pop ecx call editor_move_linestart cmp ebx, [esi + edit_block_header.limit] jb @f sub ebx, [esi + edit_block_header.limit] mov esi, [esi + edit_block_header.next] add esi, ebp add ebx, [EditBlockStart] @@: clc ret .nomem: pop eax pop ecx pop ecx add esi, ebp stc ret editor_delete_symbol: push 1 pop ecx editor_delete_space: ; Удаляет ecx байт из текста, начиная с esi:ebx ; ecx, esi, ebx разрушаются mov eax, [esi + edit_block_header.limit] sub eax, ebx cmp eax, ecx jb .more1 push esi sub [esi + edit_block_header.limit], ecx sub eax, ecx lea edi, [esi+ebx] lea esi, [edi+ecx] mov ecx, eax rep movsb pop esi .done: call .collapse_prev call .collapse_next call editor_init_lines jmp editor_update_cur .more1: mov [esi + edit_block_header.limit], ebx sub ecx, eax @@: mov esi, [esi + edit_block_header.next] add esi, ebp mov eax, [esi + edit_block_header.limit] sub eax, [EditBlockStart] sub ecx, eax jb @f call .delete_block jmp @b @@: add ecx, eax push esi mov eax, [esi + edit_block_header.limit] sub [esi + edit_block_header.limit], ecx add eax, esi add esi, [EditBlockStart] mov edi, esi add esi, ecx sub eax, esi mov ecx, esi rep movsb pop esi call .collapse_next mov esi, [esi + edit_block_header.prev] add esi, ebp jmp .done .delete_block: mov eax, [esi + edit_block_header.next] mov edx, [esi + edit_block_header.prev] test eax, eax jz .dbfirst mov [eax + ebp + edit_block_header.prev], edx jmp @f .dbfirst: mov [ebp + editor_data.first_block], edx @@: test edx, edx jz .dblast mov [edx + ebp + edit_block_header.next], eax jmp @f .dblast: mov [ebp + editor_data.last_block], eax @@: mov eax, [ebp + editor_data.freeblocks] mov [esi], eax sub esi, ebp mov [ebp + editor_data.freeblocks], esi inc [ebp + editor_data.numfree] ret .collapse_prev: mov eax, [esi + edit_block_header.prev] test eax, eax jz .cpno add eax, ebp mov edx, [esi + edit_block_header.limit] sub edx, [EditBlockStart] add edx, [eax + edit_block_header.limit] cmp edx, 4096 - edit.RESERVE_IN_BLOCK ja .cpno mov edi, eax .collapse: ; (edi) + (esi) -> (edi) push edi push esi mov ecx, [esi + edit_block_header.limit] sub ecx, [EditBlockStart] add esi, [EditBlockStart] mov eax, [edi + edit_block_header.limit] add [edi + edit_block_header.limit], ecx add edi, eax rep movsb pop esi call .delete_block pop esi .cpno: ret .collapse_next: mov eax, [esi + edit_block_header.next] test eax, eax jz .cpno add eax, ebp mov edx, [esi + edit_block_header.limit] sub edx, [EditBlockStart] add edx, [eax + edit_block_header.limit] cmp edx, 4096 - edit.RESERVE_IN_BLOCK ja .cpno mov edi, esi mov esi, eax jmp .collapse editor_OnKey: test al, 80h jnz .ret test [ebp + editor_data.flags], 20h jnz .symbol mov esi, editor_ctrlkeys call process_ctrl_keys jnc .ret .symbol: and [ebp + editor_data.flags], not 20h test [ebp + editor_data.flags], 40h jnz .ret or [ebp + editor_data.flags], 80h movzx eax, al call get_ascii_char mov esi, [ebp + editor_data.cur_block] add esi, ebp mov ebx, [ebp + editor_data.cur_offs] cmp al, 10 jz .insert_newline cmp al, 13 jz .insert_newline cmp [ebp + editor_data.cur_delta], -1 jnz .insert_after_eol test [ebp + editor_data.flags], 10h jnz .replace_symbol push eax call editor_reserve_symbol pop eax jc .ret .replace_symbol: cmp ebx, [esi + edit_block_header.limit] jnz @f mov esi, [esi + edit_block_header.next] add esi, ebp mov ebx, [EditBlockStart] @@: mov [esi + ebx], al .symb_inserted: call .redraw_curline jmp .right .redraw_curline: call editor_curline_start mov edx, [cursor_y] call editor_draw_line .ret: ret .insert_after_eol: mov ecx, [ebp + editor_data.cur_delta] inc ecx push eax call editor_reserve_space pop eax jc .ret push eax mov edx, ecx .2: mov ecx, [esi + edit_block_header.limit] sub ecx, ebx lea edi, [esi + ebx] cmp ecx, edx jb @f mov ecx, edx @@: add ebx, ecx sub edx, ecx mov al, ' ' rep stosb jz @f mov esi, [esi + edit_block_header.next] add esi, ebp mov ebx, [EditBlockStart] jmp .2 @@: pop eax mov [edi-1], al dec ebx sub esi, ebp mov [ebp + editor_data.cur_block], esi mov [ebp + editor_data.cur_offs], ebx or [ebp + editor_data.cur_delta], -1 jmp .symb_inserted .insert_newline: push 1 pop ecx cmp [ebp + editor_data.eol], 2 adc ecx, 0 call editor_reserve_space jc .ret ; Просто так вставлять символ новой строки чревато - из-за существования двухбайтовых комбинаций перевода строки ; старый символ может слиться с новым. В таком случае придётся заниматься корректировкой. ; Проблема бывает в двух случаях: ; если редактор настроен на Unix-стиль и новый перевод строки вставляется непосредственно после ; перевода строки в Mac-стиле; ; если редактор настроен на Mac-стиль и новый перевод строки вставляется непосредственно перед ; переводом строки в Unix-стиле. ; В этих случаях форсируем перевод строки в текущем стиле файла. mov al, [ebp + editor_data.eol] cmp al, edit.eol_dos jz .insert_eol_dos cmp al, edit.eol_mac jz .insert_eol_mac mov al, 10 ; Unix-style for end-of-line push esi ebx call editor_step_backward jc @f cmp byte [esi+ebx], 13 jnz @f mov al, 13 ; force Mac-style to avoid collapse @@: pop ebx esi mov [esi+ebx], al jmp .eol_correct .insert_eol_mac: mov al, 13 ; Mac-style for end-of-line push esi ebx call editor_step_forward jnc @f cmp byte [esi+ebx], 10 jnz @f mov al, 10 ; force Unix-style to avoid collapse @@: pop ebx esi mov [esi+ebx], al jmp .eol_correct .insert_eol_dos: mov byte [esi+ebx], 13 call editor_step_forward mov byte [esi+ebx], 10 .eol_correct: call editor_step_forward test esi, esi jnz @f mov esi, [ebp + editor_data.last_block] add esi, ebp mov ebx, [esi + edit_block_header.limit] @@: and [ebp + editor_data.cur_delta], 0 cmp ebx, [esi + edit_block_header.limit] jz @f mov al, [esi+ebx] cmp al, 10 jz @f cmp al, 13 jz @f dec [ebp + editor_data.cur_delta] @@: ; ну что же, в текст нужные символы вставили, теперь надо скорректировать информацию о начале строк на экране mov edi, [ebp + editor_data.cursor_y] mov ecx, max_height-1 sub ecx, edi dec edi mov eax, [EditPlugInfo] add eax, editor_line.plugdata imul edi, eax, max_height imul ecx, eax lea edi, [ebp + edi + editor_data.linedata_start - 2] push esi mov esi, edi sub esi, eax shr ecx, 1 std rep movsw cld pop esi add edi, 2 sub edi, eax push esi mov esi, edi sub esi, eax pop eax stosd ; editor_line.block sub eax, ebp mov [ebp + editor_data.cur_block], eax mov eax, ebx stosw ; editor_line.offs mov [ebp + editor_data.cur_offs], eax ;mov eax, ecx ;stosd ; editor_line.length mov ecx, [EditPlugInfo] xor eax, eax rep stosb ; на одну строку стало больше inc [ebp + editor_data.numlines] ; курсор окажется в начале строки mov [ebp + editor_data.cursor_x], eax mov [ebp + editor_data.curcol], eax mov [cursor_x], eax ; и передвинется на строку ниже mov eax, [ebp + editor_data.cursor_y] inc eax mov edx, [cur_height] dec edx cmp eax, edx jae .down_scroll mov [ebp + editor_data.cursor_y], eax mov [cursor_y], eax jmp editor_draw_text .exit_confirm: test [ebp + editor_data.flags], 80h jz .exit push aFileModified mov eax, esp push EditorExitBtn push 3 push eax push 1 push aEditorTitle call SayErrTitle pop ecx test eax, eax jz .save dec eax jz .exit ret .exit_save: test [ebp + editor_data.flags], 80h jz .exit .save: call editor_save .exit: call editor_OnExit jmp delete_active_screen .f2: call editor_save jmp .redraw_status .up_scroll: cmp [ebp + editor_data.curline], 0 jz .ret push 1 pop ecx call editor_up_scroll jmp editor_draw_text .up: mov eax, [ebp + editor_data.cursor_y] dec eax jz .up_scroll .set_cursor_y: mov [ebp + editor_data.cursor_y], eax mov [cursor_y], eax call editor_update_cur test al, al jnz editor_draw_text .redraw_status: call editor_draw_status jmp draw_image .down: mov eax, [ebp + editor_data.cursor_y] inc eax push eax add eax, [ebp + editor_data.curline] cmp eax, [ebp + editor_data.numlines] pop eax ja .ret mov edx, [cur_height] dec edx cmp eax, edx jnz .set_cursor_y .down_scroll: inc [ebp + editor_data.curline] lea edi, [ebp + editor_data.linedata_start] mov eax, [EditPlugInfo] add eax, editor_line.plugdata lea esi, [edi + eax] imul ecx, eax, max_height-1 shr ecx, 2 rep movsd adc ecx, ecx rep movsw sub esi, eax sub esi, eax movzx ebx, [esi + editor_line.offs] mov esi, [esi + editor_line.block] call editor_find_newline mov eax, esi stosd ; editor_line.block mov eax, ebx stosw ; editor_line.offs ;mov eax, ecx ;stosd ; editor_line.length mov ecx, [EditPlugInfo] xor eax, eax rep stosb jmp .ret2 .pgup: mov ecx, [cur_height] sub ecx, 3 mov edx, [ebp + editor_data.curline] mov eax, edx push edx sub edx, ecx jnc @f xor edx, edx @@: mov [ebp + editor_data.curline], edx add eax, [ebp + editor_data.cursor_y] dec eax sub eax, ecx jnc @f xor eax, eax @@: sub eax, edx inc eax mov [ebp + editor_data.cursor_y], eax mov [cursor_y], eax pop ecx sub ecx, edx push ecx mov edx, [EditPlugInfo] add edx, editor_line.plugdata imul ecx, edx imul eax, edx, max_height lea edi, [ebp + editor_data.linedata_start + eax - 2] mov esi, edi sub esi, ecx sub eax, ecx mov ecx, eax shr ecx, 1 std rep movsw cld pop ecx jecxz .ret2 inc edi inc edi mov esi, [edi + editor_line.block] movzx ebx, [edi + editor_line.offs] @@: push ecx call editor_prev_newline sub edi, edx push edi mov eax, esi stosd ; editor_line.block mov eax, ebx stosw ; editor_line.offs ;mov eax, ecx ;stosd ; editor_line.length mov ecx, [EditPlugInfo] xor eax, eax rep stosb pop edi pop ecx loop @b .ret2: call editor_update_cur jmp editor_draw_text .pgdn: mov edx, [cur_height] sub edx, 2 mov ecx, [ebp + editor_data.curline] push ecx lea ecx, [edx + ecx - 1] mov eax, [ebp + editor_data.numlines] sub eax, edx jnc @f xor eax, eax @@: cmp ecx, eax jb @f mov ecx, eax @@: mov [ebp + editor_data.curline], ecx pop eax push eax add eax, [ebp + editor_data.cursor_y] lea eax, [eax + edx - 1] cmp eax, [ebp + editor_data.numlines] jb @f mov eax, [ebp + editor_data.numlines] @@: sub eax, ecx mov [ebp + editor_data.cursor_y], eax mov [cursor_y], eax pop edx sub ecx, edx call editor_down_scroll jmp .ret2 .left: call editor_cursor_left jc .redraw_status jmp editor_draw_text .ret3: ret .right: cmp [ebp + editor_data.cur_delta], -1 jz .right_in_text cmp [ebp + editor_data.curcol], 0x80000000 - 0x1000 jae .ret3 inc [ebp + editor_data.cur_delta] push 1 pop edx jmp .right_char .right_in_text: mov esi, [ebp + editor_data.cur_block] add esi, ebp mov ebx, [ebp + editor_data.cur_offs] mov al, [esi + ebx] push eax call editor_step_forward test esi, esi jz .right_eol0 mov al, [esi + ebx] cmp al, 10 jz .right_eol cmp al, 13 jz .right_eol jmp .right_ok .right_eol0: mov esi, [ebp + editor_data.last_block] add esi, ebp mov ebx, [esi + edit_block_header.limit] .right_eol: inc [ebp + editor_data.cur_delta] .right_ok: sub esi, ebp mov [ebp + editor_data.cur_block], esi mov [ebp + editor_data.cur_offs], ebx pop eax push 1 pop edx cmp al, 9 jnz .right_char mov eax, [ebp + editor_data.curcol] add eax, [ebp + editor_data.cursor_x] xor edx, edx div [editor_tabsize] sub edx, [editor_tabsize] neg edx .right_char: mov eax, [ebp + editor_data.cursor_x] add eax, edx cmp eax, [cur_width] jb .set_cursor_x add eax, [ebp + editor_data.curcol] mov edx, [cur_width] dec edx sub eax, edx mov [ebp + editor_data.cursor_x], edx mov [cursor_x], edx mov [ebp + editor_data.curcol], eax jmp editor_draw_text .set_cursor_x: mov [ebp + editor_data.cursor_x], eax mov [cursor_x], eax jmp .redraw_status .home: call editor_curline_start and [ebp + editor_data.cur_delta], 0 cmp ebx, [esi + edit_block_header.limit] jz @f mov al, [esi+ebx] cmp al, 10 jz @f cmp al, 13 jz @f dec [ebp + editor_data.cur_delta] @@: sub esi, ebp mov [ebp + editor_data.cur_block], esi mov [ebp + editor_data.cur_offs], ebx xor eax, eax mov [ebp + editor_data.cursor_x], eax mov [cursor_x], eax xchg eax, [ebp + editor_data.curcol] test eax, eax jnz editor_draw_text jmp .redraw_status .end: call editor_end_scroll jc editor_draw_text jmp .redraw_status .ins: xor [ebp + editor_data.flags], 10h mov eax, cursor_normal_size test [ebp + editor_data.flags], 10h jz @f mov eax, cursor_big_size @@: mov [cursor_size], eax jmp draw_image .backspace: cmp [ebp + editor_data.cur_delta], -1 jz @f cmp [ebp + editor_data.cur_delta], 0 jnz .left @@: test [ebp + editor_data.flags], 40h jnz .ret3 mov esi, [ebp + editor_data.cur_block] add esi, ebp mov ebx, [ebp + editor_data.cur_offs] call editor_step_backward jc .ret3 push esi ebx call editor_cursor_left pop ebx esi setc al push eax push esi ebx cmp byte [esi+ebx], 10 jnz @f call editor_step_backward jc @f cmp byte [esi+ebx], 13 jnz @f pop eax eax jmp .del_char @@: pop ebx esi jmp .del_char .del: test [ebp + editor_data.flags], 40h jnz .ret3 mov esi, [ebp + editor_data.cur_block] add esi, ebp mov ebx, [ebp + editor_data.cur_offs] call editor_normalize_offs jnc .ret3 push 0 .del_char: or [ebp + editor_data.flags], 80h mov al, [esi+ebx] push 1 pop ecx push eax push esi ebx cmp al, 13 jnz @f call editor_step_forward jnc @f cmp byte [esi+ebx], 10 jnz @f inc ecx @@: pop ebx esi call editor_delete_space pop eax cmp al, 13 jz @f cmp al, 10 jz @f pop eax test al, al jnz .del1 call .redraw_curline jmp .redraw_status @@: pop eax dec [ebp + editor_data.numlines] call editor_test_cursor_y .del1: jmp editor_draw_text editor_cursor_left: cmp [ebp + editor_data.cur_delta], -1 jz .in_text dec [ebp + editor_data.cur_delta] cmp [ebp + editor_data.cur_delta], -1 jnz .left_cursor .in_text: mov esi, [ebp + editor_data.cur_block] add esi, ebp mov ebx, [ebp + editor_data.cur_offs] call editor_step_backward jc .ret_clc mov al, [esi + ebx] cmp al, 13 jz .eol cmp al, 10 jz .eol2 cmp al, 9 jz .tab sub esi, ebp mov [ebp + editor_data.cur_block], esi mov [ebp + editor_data.cur_offs], ebx .left_cursor: mov eax, [ebp + editor_data.cursor_x] test eax, eax jz @f dec eax .set_cursor_x: mov [ebp + editor_data.cursor_x], eax mov [cursor_x], eax .ret_clc: clc ret @@: dec [ebp + editor_data.curcol] jmp .ret_stc .tab: mov eax, [ebp + editor_data.cursor_x] test eax, eax jz @f dec eax mov [ebp + editor_data.cursor_x], eax mov [cursor_x], eax call editor_update_cur test al, al jz .ret_clc .ret_stc: stc ret @@: dec [ebp + editor_data.curcol] call editor_update_cur jmp .ret_stc .eol2: push esi ebx call editor_step_backward jc @f cmp byte [esi + ebx], 13 jnz @f pop eax eax push esi ebx @@: pop ebx esi .eol: mov eax, [ebp + editor_data.cursor_y] dec eax jz .scroll_left_toup push 0 ; no full redraw mov [ebp + editor_data.cursor_y], eax mov [cursor_y], eax jmp .scroll_left_toend .scroll_left_toup: push 1 pop ecx call editor_up_scroll push 1 ; full redraw required .scroll_left_toend: call editor_end_scroll pop eax adc al, 0 jnz .ret_stc jmp .ret_clc editor_test_cursor_x: mov ecx, [cur_width] dec ecx mov eax, [ebp + editor_data.cursor_x] sub eax, ecx jbe @f add [ebp + editor_data.curcol], eax mov [ebp + editor_data.cursor_x], ecx mov [cursor_x], ecx @@: ret editor_test_cursor_y: mov ecx, [ebp + editor_data.cursor_y] mov edx, [cur_height] dec edx dec edx sub ecx, edx ja .scroll_down mov ecx, [ebp + editor_data.curline] add ecx, edx sub ecx, [ebp + editor_data.numlines] ja .scroll_up .clc_ret: clc ret .scroll_down: add [ebp + editor_data.curline], ecx sub [ebp + editor_data.cursor_y], ecx sub [cursor_y], ecx call editor_down_scroll stc ret .scroll_up: cmp ecx, [ebp + editor_data.curline] jb @f mov ecx, [ebp + editor_data.curline] @@: jecxz .clc_ret add [ebp + editor_data.cursor_y], ecx add [cursor_y], ecx call editor_up_scroll stc ret editor_OnExit: mov edx, [ebp+editor_data.hPlugin] test edx, edx jz @f mov ebx, [ebp+editor_data.hFile] call close_handle_if_unused @@: ret