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