
; flat assembler IDE for DOS/DPMI
; Copyright (c) 1999-2011, Tomasz Grysztar.
; All rights reserved.

	format	MZ
	heap	0
	stack	stack_segment:stack_top-stack_bottom
	entry	loader:init

segment loader use16

init:

	mov	ax,3301h
	xor	dl,dl
	int	21h
	push	ds cs
	pop	ds
	mov	ax,2524h
	mov	dx,dos_error_handler
	int	21h
	pop	ds

	mov	ax,1A00h
	xor	bx,bx
	int	10h
	cmp	al,1Ah
	jne	short no_vga
	cmp	bl,8
	jne	short no_vga

	mov	ax,1687h
	int	2Fh
	or	ax,ax			; DPMI installed?
	jnz	short no_dpmi
	test	bl,1			; 32-bit programs supported?
	jz	short no_dpmi
	mov	word [cs:mode_switch],di
	mov	word [cs:mode_switch+2],es
	mov	bx,si			; allocate memory for DPMI data
	mov	ah,48h
	int	21h
	jnc	switch_to_protected_mode
  init_failed:
	call	init_error
	db	'DPMI initialization failed.',0Dh,0Ah,0
  no_vga:
	call	init_error
	db	'Color VGA adapter is required.',0Dh,0Ah,0
  no_dpmi:
	call	init_error
	db	'32-bit DPMI services are not available.',0Dh,0Ah,0
  init_error:
	pop	si
	push	cs
	pop	ds
      display_error:
	lodsb
	test	al,al
	jz	short error_finish
	mov	dl,al
	mov	ah,2
	int	21h
	jmp	short display_error
      error_finish:
	mov	ax,4CFFh
	int	21h
  dos_error_handler:
	mov	al,3
	iret
  switch_to_protected_mode:
	mov	es,ax
	mov	ds,[ds:2Ch]
	mov	ax,1
	call	far [cs:mode_switch]	; switch to protected mode
	jc	init_failed
	mov	cx,1
	xor	ax,ax
	int	31h			; allocate descriptor for code
	jc	init_failed
	mov	si,ax
	xor	ax,ax
	int	31h			; allocate descriptor for data
	jc	init_failed
	mov	di,ax
	mov	dx,cs
	lar	cx,dx
	shr	cx,8
	or	cx,0C000h
	mov	bx,si
	mov	ax,9
	int	31h			; set code descriptor access rights
	jc	init_failed
	mov	dx,ds
	lar	cx,dx
	shr	cx,8
	or	cx,0C000h
	mov	bx,di
	int	31h			; set data descriptor access rights
	jc	init_failed
	mov	ecx,main
	shl	ecx,4
	mov	dx,cx
	shr	ecx,16
	mov	ax,7
	int	31h			; set data descriptor base address
	jc	init_failed
	mov	bx,si
	int	31h			; set code descriptor base address
	jc	init_failed
	mov	cx,0FFFFh
	mov	dx,0FFFFh
	mov	ax,8			; set segment limit to 4 GB
	int	31h
	jc	init_failed
	mov	bx,di
	int	31h
	jc	init_failed
	mov	ax,ds
	mov	ds,di
	mov	[main_selector],di
	mov	[psp_selector],es
	mov	[environment_selector],ax
	cli
	mov	ss,di
	mov	esp,stack_top
	sti
	mov	es,di
	mov	cx,1
	xor	ax,ax
	int	31h			; allocate descriptor for BIOS data segment
	jc	init_failed
	mov	bx,ax
	lar	cx,[environment_selector]
	shr	cx,8
	mov	ax,9
	int	31h			; set descriptor access rights
	jc	init_failed
	xor	cx,cx
	mov	dx,400h
	mov	ax,7
	int	31h			; set base address of BIOS data segment
	jc	init_failed
	xor	cx,cx
	mov	dx,0FFh
	mov	ax,8
	int	31h			; set limit of BIOS data segment
	jc	init_failed
	mov	fs,bx
	mov	[bios_selector],bx
	mov	cx,1
	xor	ax,ax
	int	31h			; allocate descriptor for video segment
	jc	init_failed
	mov	bx,ax
	lar	cx,[environment_selector]
	shr	cx,8
	mov	ax,9
	int	31h			; set descriptor access rights
	jc	init_failed
	mov	cx,0Bh
	mov	dx,8000h
	mov	ax,7
	int	31h			; set base address of video segment
	jc	init_failed
	xor	cx,cx
	mov	dx,4000-1
	mov	ax,8
	int	31h			; set limit of video segment
	jc	init_failed
	mov	gs,bx
	mov	[video_selector],bx
	push	si
	push	start
	retf

  mode_switch dd ?

segment main use32

  start:
	call	init_video
	jc	startup_failed

	call	init_editor_memory
	jc	startup_failed

	mov	eax,[undo_data]
	mov	[unmodified_state],eax

	xor	eax,eax
	mov	[next_instance],eax
	mov	[previous_instance],eax
	mov	[file_path],eax

	mov	ecx,1000h
	mov	[line_buffer_size],ecx
	call	get_memory
	or	eax,eax
	jz	startup_failed
	mov	[line_buffer],eax
	mov	[line_buffer_handle],ebx

	mov	[stack_limit],stack_bottom

	mov	edi,upper_case_table
	xor	al,al
	mov	ecx,80h
      prepare_case_table:
	stosb
	inc	al
	loop	prepare_case_table
      make_extended_case_table:
	push	eax
	mov	dl,al
	mov	ax,6520h
	int	21h
	mov	al,[esp]
	jc	upper_case_character_ok
	mov	al,dl
      upper_case_character_ok:
	stosb
	pop	eax
	inc	al
	jnz	make_extended_case_table
	mov	esi,upper_case_table+'A'
	mov	edi,upper_case_table+'a'
	mov	ecx,26
	rep	movsb
	xor	al,al
	mov	edi,lower_case_table
      prepare_lower_case_table:
	stosb
	inc	al
	jnz	prepare_lower_case_table
	mov	esi,lower_case_table+'a'
	mov	edi,lower_case_table+'A'
	mov	ecx,26
	rep	movsb
	mov	eax,80h
	xor	edx,edx
      make_lower_case_table:
	mov	dl,[upper_case_table+eax]
	cmp	al,dl
	je	lower_case_character_ok
	cmp	dl,80h
	jb	lower_case_character_ok
	mov	[lower_case_table+edx],al
      lower_case_character_ok:
	inc	al
	jnz	make_lower_case_table
	mov	edi,characters
	xor	al,al
      prepare_characters_table:
	stosb
	inc	al
	jnz	prepare_characters_table
	mov	esi,characters+'a'
	mov	edi,characters+'A'
	mov	ecx,26
	rep	movsb
	mov	edi,characters
	mov	esi,symbol_characters+1
	movzx	ecx,byte [esi-1]
	xor	eax,eax
      convert_table:
	lodsb
	mov	byte [edi+eax],0
	loop	convert_table
	mov	[selected_character],'p'

	call	get_low_memory

	push	ds
	mov	ds,[environment_selector]
	xor	esi,esi
	mov	edi,ini_path
      skip_environment:
	lodsb
	test	al,al
	jnz	skip_environment
	lodsb
	test	al,al
	jnz	skip_environment
	add	esi,2
      copy_program_path:
	lodsb
	stosb
	test	al,al
	jnz	copy_program_path
	pop	ds
	dec	edi
	mov	edx,edi
      find_extension_start:
	cmp	edi,ini_path
	je	attach_extension
	cmp	byte [edi-1],'.'
	je	replace_extension
	cmp	byte [edi-1],'/'
	je	attach_extension
	dec	edi
	jmp	find_extension_start
      attach_extension:
	mov	edi,edx
	mov	al,'.'
	stosb
      replace_extension:
	mov	eax,'INI'
	stosd

	xor	eax,eax
	mov	[ini_data],eax
	mov	[main_project_file],eax
	mov	[clipboard],eax
	mov	[last_operation],al
	mov	[find_flags],eax
	mov	[command_flags],al

	call	load_configuration

	call	update_positions
	call	switch_to_ide_screen

	mov	esi,81h
      process_arguments:
	push	ds
	mov	ds,[psp_selector]
	mov	edi,filename_buffer
      find_argument:
	lodsb
	cmp	al,20h
	je	find_argument
	cmp	al,9
	je	find_argument
	cmp	al,22h
	je	quoted_argument
	dec	esi
      copy_argument:
	lodsb
	cmp	al,20h
	je	argument_end
	cmp	al,9
	je	argument_end
	cmp	al,0Dh
	je	argument_end
	stosb
	jmp	copy_argument
      quoted_argument:
	lodsb
	cmp	al,0Dh
	je	argument_end
	stosb
	cmp	al,22h
	jne	quoted_argument
	lodsb
	cmp	al,22h
	je	quoted_argument
	dec	edi
      argument_end:
	dec	esi
	pop	ds
	cmp	edi,filename_buffer
	je	main_loop
	xor	al,al
	stosb
	push	esi
	mov	edx,filename_buffer
	call	load_file
	pop	esi
	jmp	process_arguments

  main_loop:

	call	update_cursor
	call	update_screen

	xor	al,al
	xchg	[current_operation],al
	mov	[last_operation],al
	mov	[was_selection],1
	mov	eax,[selection_line]
	or	eax,eax
	jz	no_selection
	cmp	eax,[caret_line]
	jne	get_command
	mov	eax,[selection_position]
	cmp	eax,[caret_position]
	jne	get_command
    no_selection:
	mov	[was_selection],0
	mov	eax,[caret_line]
	mov	[selection_line],eax
	mov	eax,[caret_position]
	mov	[selection_position],eax
	mov	eax,[caret_line_number]
	mov	[selection_line_number],eax
    get_command:
	call	wait_for_input
	cmp	ah,1
	je	close_editor
	jb	character
	cmp	al,0Eh
	je	new_editor
	cmp	ah,94h
	je	switch_editor
	cmp	ah,0A5h
	je	switch_editor
	cmp	ah,3Ch
	je	save_current
	cmp	ah,55h
	je	save_as
	cmp	ah,3Eh
	je	open_file
	cmp	ah,3Fh
	je	goto
	cmp	ah,41h
	je	search
	cmp	ah,5Ah
	je	search_next
	cmp	ah,64h
	je	replace
	cmp	ah,43h
	je	compile_and_run
	cmp	ah,66h
	je	compile
	cmp	ah,65h
	je	build_symbols
	cmp	ah,5Ch
	je	assign_to_compiler
	cmp	ah,63h
	je	calculator
	cmp	ah,6Ch
	je	show_user_screen
	cmp	ah,44h
	je	options
	cmp	ah,3Dh
	je	search_next
	test	byte [fs:17h],1000b
	jz	no_alt
	cmp	ah,2Dh
	je	close_all
	cmp	ah,0Eh
	je	undo
	cmp	ah,0A3h
	je	emptyundobuffer
	cmp	ah,98h
	je	scroll_up
	cmp	ah,0A0h
	je	scroll_down
	cmp	ah,9Bh
	je	scroll_left
	cmp	ah,9Dh
	je	scroll_right
      no_alt:
	or	al,al
	jz	no_ascii
	cmp	al,0E0h
	jne	ascii
      no_ascii:
	cmp	ah,4Bh
	je	left_key
	cmp	ah,4Dh
	je	right_key
	cmp	ah,48h
	je	up_key
	cmp	ah,50h
	je	down_key
	cmp	ah,47h
	je	home_key
	cmp	ah,4Fh
	je	end_key
	cmp	ah,77h
	je	screen_home
	cmp	ah,75h
	je	screen_end
	cmp	ah,73h
	je	word_left
	cmp	ah,74h
	je	word_right
	cmp	ah,8Dh
	je	word_left
	cmp	ah,91h
	je	word_right
	cmp	ah,49h
	je	pgup_key
	cmp	ah,51h
	je	pgdn_key
	cmp	ah,84h
	je	text_home
	cmp	ah,76h
	je	text_end
	cmp	ah,52h
	je	ins_key
	cmp	ah,0A2h
	je	switch_blocks
	cmp	ah,40h
	je	f6_key
	cmp	ah,93h
	je	block_delete
	cmp	ah,92h
	je	block_copy
	cmp	ah,53h
	je	del_key
	cmp	ah,78h
	jb	get_command
	cmp	ah,80h
	ja	get_command
	sub	ah,77h
	movzx	ecx,ah
	jmp	select_editor
      ascii:
	cmp	al,7Fh
	je	word_back
	cmp	al,20h
	jae	character
	cmp	al,8
	je	backspace_key
	cmp	al,9
	je	tab_key
	cmp	al,0Dh
	je	enter_key
	cmp	al,19h
	je	ctrl_y_key
	cmp	al,1Ah
	je	undo
	cmp	al,18h
	je	block_cut
	cmp	al,3
	je	block_copy
	cmp	al,16h
	je	block_paste
	cmp	al,0Fh
	je	open_file
	cmp	al,13h
	je	save_current
	cmp	al,6
	je	search
	cmp	al,7
	je	goto
	cmp	al,1
	je	select_all
	cmp	al,2
	je	ascii_table
	jmp	get_command
  character:
	cmp	[was_selection],0
	je	no_selection_to_replace
	call	store_status_for_undo
	test	[editor_style],AES_SECURESEL
	jnz	character_undo_ok
	push	eax
	call	delete_block
	pop	eax
	call	put_character
	mov	esi,[caret_line]
	call	check_line_length
	mov	[selection_line],0
	jmp	text_modified
    no_selection_to_replace:
	mov	[current_operation],20h
	cmp	[last_operation],20h
	je	character_undo_ok
	mov	edx,[unmodified_state]
	cmp	edx,[undo_data]
	jne	character_undo_ok
	or	[unmodified_state],-1
	jmp	character_undo_ok
    character_undopoint:
	call	store_status_for_undo
    character_undo_ok:
	call	put_character
	mov	esi,[caret_line]
	call	check_line_length
	mov	[selection_line],0
	jmp	text_modified
  tab_key:
	call	store_status_for_undo
	cmp	[was_selection],0
	je	tab_securesel
	test	[editor_style],AES_SECURESEL
	jnz	tab_securesel
	call	delete_block
    tab_securesel:
	call	tabulate
	mov	[selection_line],0
	mov	esi,[caret_line]
	call	check_line_length
	jmp	text_modified
  enter_key:
	call	store_status_for_undo
	cmp	[was_selection],0
	je	enter_secureselection_ok
	test	[editor_style],AES_SECURESEL
	jnz	enter_secureselection_ok
	call	delete_block
    enter_secureselection_ok:
	call	carriage_return
	mov	[selection_line],0
	test	[editor_mode],AEMODE_OVERWRITE
	jnz	text_modified
	mov	esi,[caret_line]
	call	check_line_length
	jmp	text_modified
  backspace_key:
	test	byte [fs:17h],100b
	jnz	replace
	cmp	[was_selection],0
	je	no_selection_to_clear
	test	[editor_style],AES_SECURESEL
	jz	block_delete
    no_selection_to_clear:
	cmp	[caret_position],0
	je	line_back
	mov	[current_operation],8
	cmp	[last_operation],8
	je	undo_back_ok
	call	store_status_for_undo
    undo_back_ok:
	dec	[caret_position]
	call	delete_character
	mov	esi,[caret_line]
	call	check_line_length
	mov	[selection_line],0
	jmp	text_modified
    line_back:
	test	[editor_mode],AEMODE_OVERWRITE
	jnz	get_command
	mov	esi,[caret_line]
	mov	esi,[esi+4]
	or	esi,esi
	jz	get_command
	call	store_status_for_undo
	mov	[caret_line],esi
	dec	[caret_line_number]
	call	check_line_length
	mov	[caret_position],ecx
	call	cut_line_break
	mov	esi,[caret_line]
	call	check_line_length
	mov	[selection_line],0
	jmp	text_modified
    word_back:
	call	store_status_for_undo
	push	[caret_position]
	mov	esi,[caret_line]
	xor	eax,eax
	xchg	eax,[esi+4]
	push	eax
	call	move_to_previous_word
	pop	eax
	mov	esi,[caret_line]
	mov	[esi+4],eax
	pop	ecx
	sub	ecx,[caret_position]
	call	delete_from_line
	mov	esi,[caret_line]
	call	check_line_length
	jmp	text_modified
  del_key:
	test	byte [fs:17h],11b
	jnz	block_cut
	cmp	[was_selection],0
	je	no_selection_on_del
	test	[editor_style],AES_SECURESEL
	jz	block_delete
    no_selection_on_del:
	mov	esi,[caret_line]
	test	[editor_mode],AEMODE_OVERWRITE
	jnz	delete_char
	call	check_line_length
	cmp	ecx,[caret_position]
	ja	delete_char
	cmp	dword [esi],0
	je	get_command
	call	store_status_for_undo
	call	cut_line_break
	mov	esi,[caret_line]
	call	check_line_length
	mov	[selection_line],0
	jmp	text_modified
    delete_char:
	mov	[current_operation],0E0h
	cmp	[last_operation],0E0h
	je	undo_delete_ok
	call	store_status_for_undo
    undo_delete_ok:
	call	delete_character
	mov	esi,[caret_line]
	call	check_line_length
	mov	[selection_line],0
	jmp	text_modified
  ctrl_y_key:
	call	store_status_for_undo
	call	remove_line
	jmp	text_modified
  f6_key:
	call	store_status_for_undo
	call	duplicate_line
	jmp	text_modified
  left_key:
	cmp	[caret_position],0
	jle	text_modified
	dec	[caret_position]
	jmp	moved_caret
  right_key:
	mov	eax,[caret_position]
	cmp	eax,[maximum_position]
	jae	text_modified
	inc	[caret_position]
	jmp	moved_caret
  up_key:
	call	move_line_up
	jmp	moved_caret
  down_key:
	call	move_line_down
	jmp	moved_caret
  home_key:
	mov	[caret_position],0
	jmp	moved_caret
  end_key:
	call	move_to_line_end
	jmp	moved_caret
  screen_home:
	mov	eax,[window_line]
	mov	[caret_line],eax
	mov	eax,[window_line_number]
	mov	[caret_line_number],eax
	jmp	moved_caret
  screen_end:
	mov	eax,[window_line_number]
	add	eax,[window_height]
	dec	eax
	call	find_line
	mov	[caret_line],esi
	mov	[caret_line_number],ecx
	jmp	moved_caret
  pgup_key:
	call	move_page_up
	jmp	moved_caret
  pgdn_key:
	call	move_page_down
	jmp	moved_caret
  text_home:
	mov	eax,[first_line]
	mov	[caret_line],eax
	mov	[caret_line_number],1
	jmp	moved_caret
  text_end:
	or	eax,-1
	call	find_line
	mov	[caret_line],esi
	mov	[caret_line_number],ecx
	jmp	moved_caret
  word_left:
	call	move_to_previous_word
	jmp	moved_caret
  word_right:
	call	get_caret_segment
	call	move_to_next_word
	jmp	moved_caret
  scroll_left:
	cmp	[window_position],0
	je	main_loop
	dec	[window_position]
	jmp	moved_window
  scroll_right:
	inc	[window_position]
	jmp	moved_window
  scroll_up:
	mov	esi,[window_line]
	mov	esi,[esi+4]
	or	esi,esi
	jz	main_loop
	mov	[window_line],esi
	dec	[window_line_number]
	jmp	moved_window
  scroll_down:
	mov	esi,[window_line]
      find_next_window_line:
	mov	esi,[esi]
	btr	esi,0
	jc	find_next_window_line
	or	esi,esi
	jz	main_loop
	mov	[window_line],esi
	inc	[window_line_number]
	jmp	moved_window
  ins_key:
	and	byte [fs:18h],not 80h
	test	byte [fs:17h],11b
	jnz	block_paste
  switch_mode:
	xor	[editor_mode],AEMODE_OVERWRITE
	jmp	main_loop
  switch_blocks:
	xor	[editor_mode],AEMODE_VERTICALSEL
	jmp	main_loop
  block_delete:
	cmp	[was_selection],0
	je	get_command
	call	store_status_for_undo
	call	delete_block
	mov	[selection_line],0
	jmp	operation_done
  block_copy:
	cmp	[was_selection],0
	je	get_command
	call	copy_to_clipboard
	jmp	get_command
    copy_to_clipboard:
	cmp	[clipboard],0
	je	allocate_clipboard
	mov	ebx,[clipboard_handle]
	call	release_memory
    allocate_clipboard:
	call	get_block_length
	inc	ecx
	call	get_memory
	mov	[clipboard],eax
	mov	[clipboard_handle],ebx
	or	eax,eax
	jz	not_enough_memory
	mov	edi,[clipboard]
	call	copy_block
	retn
  block_cut:
	cmp	[was_selection],0
	je	get_command
	call	copy_to_clipboard
	jmp	block_delete
  block_paste:
	call	store_status_for_undo
	cmp	[was_selection],0
	je	paste_secureselection_ok
	test	[editor_style],AES_SECURESEL
	jnz	paste_secureselection_ok
	call	delete_block
    paste_secureselection_ok:
	mov	esi,[clipboard]
	or	esi,esi
	jz	operation_done
	call	insert_block
	jc	paste_failed
	test	[editor_style],AES_SECURESEL
	jz	no_selection_after_paste
	mov	eax,[caret_line]
	mov	ecx,[caret_line_number]
	mov	edx,[caret_position]
	xchg	eax,[selection_line]
	xchg	ecx,[selection_line_number]
	xchg	edx,[selection_position]
	mov	[caret_line],eax
	mov	[caret_line_number],ecx
	mov	[caret_position],edx
	jmp	operation_done
    no_selection_after_paste:
	mov	[selection_line],0
	jmp	operation_done
    paste_failed:
	call	undo_changes
	jmp	operation_done
  undo:
	mov	eax,[undo_data]
	test	eax,eax
	jz	get_command
	push	eax
	call	undo_changes
	pop	eax
	mov	[last_operation],0
	cmp	eax,[unmodified_state]
	jne	operation_done
	or	[unmodified_state],-1
	jmp	operation_done
  emptyundobuffer:
	push	[undo_data]
	call	clear_undo_data
	pop	eax
	xor	edx,edx
	xchg	edx,[unmodified_state]
	cmp	eax,edx
	je	operation_done
	or	[unmodified_state],-1
	jmp	operation_done
  select_all:
	or	eax,-1
	call	find_line
	mov	[caret_line],esi
	mov	[caret_line_number],ecx
	call	check_line_length
	mov	[caret_position],ecx
	mov	eax,1
	call	find_line
	mov	[selection_line],esi
	mov	[selection_line_number],ecx
	mov	[selection_position],0
	jmp	operation_done
  ascii_table:
	call	ascii_table_window
	jc	main_loop
	jmp	character

  moved_caret:
	test	byte [fs:17h],11b
	jnz	operation_done
	mov	[selection_line],0
	jmp	operation_done
  text_modified:
	cmp	[was_selection],0
	jne	operation_done
	mov	[selection_line],0
  operation_done:
	call	update_positions
	call	let_caret_appear
	call	update_window
	jmp	main_loop
  moved_window:
	call	update_positions
	cmp	[was_selection],0
	jne	main_loop
	mov	[selection_line],0
	jmp	main_loop

  new_editor:
	call	create_editor_instance
	jmp	main_loop
  close_editor:
	or	[command_flags],8
	jmp	closing_loop
  close_all:
	and	[command_flags],not 8
    closing_loop:
	mov	eax,[undo_data]
	cmp	eax,[unmodified_state]
	je	do_close
	mov	esi,[file_path]
	call	get_file_title
	mov	ebx,esi
	mov	esi,_saving_question
	mov	eax,2 shl 24
	mov	ax,[message_box_colors]
	mov	[first_button],_yes
	mov	[second_button],_no
	call	message_box
	cmp	eax,1
	jb	main_loop
	ja	do_close
	cmp	[file_path],0
	jne	save_before_closing
	call	get_saving_path
	jc	main_loop
    save_before_closing:
	call	save_file
	jc	main_loop
    do_close:
	call	remove_editor_instance
	jc	shutdown
	test	[command_flags],8
	jnz	main_loop
	call	update_cursor
	call	update_screen
	jmp	closing_loop
  switch_editor:
	test	byte [fs:17h],11b
	jnz	previous_editor
	mov	eax,[next_instance]
	or	eax,eax
	jnz	do_switch
	mov	eax,[previous_instance]
	or	eax,eax
	jz	get_command
    find_first_editor:
	mov	ebx,[eax+SEGMENT_HEADER_LENGTH+previous_instance-editor_data]
	or	ebx,ebx
	jz	do_switch
	mov	eax,ebx
	jmp	find_first_editor
    do_switch:
	call	switch_editor_instance
	jmp	main_loop
    previous_editor:
	mov	eax,[previous_instance]
	or	eax,eax
	jnz	do_switch
	mov	eax,[next_instance]
	or	eax,eax
	jz	get_command
    find_last_editor:
	mov	ebx,[eax+SEGMENT_HEADER_LENGTH+next_instance-editor_data]
	or	ebx,ebx
	jz	do_switch
	mov	eax,ebx
	jmp	find_last_editor
  select_editor:
	mov	eax,[editor_memory]
	mov	edx,[previous_instance]
    prepare_for_editor_counting:
	or	edx,edx
	jz	find_selected_editor
	mov	eax,edx
	mov	edx,[edx+SEGMENT_HEADER_LENGTH+previous_instance-editor_data]
	jmp	prepare_for_editor_counting
    find_selected_editor:
	dec	ecx
	jz	selected_editor_found
	mov	eax,[eax+SEGMENT_HEADER_LENGTH+next_instance-editor_data]
	or	eax,eax
	jz	get_command
	jmp	find_selected_editor
    selected_editor_found:
	cmp	eax,[editor_memory]
	je	get_command
	jmp	do_switch
  show_user_screen:
	call	switch_to_user_screen
	mov	ah,10h
	int	16h
	call	switch_to_ide_screen
	jmp	main_loop

  save_current:
	cmp	[file_path],0
	jne	do_save
  save_as:
	call	get_saving_path
	jc	main_loop
      do_save:
	call	save_file
	jmp	main_loop
  open_file:
	mov	esi,_open
	call	file_open_dialog
	jc	main_loop
	call	load_file
	jmp	main_loop
  goto:
	call	goto_dialog
	jc	main_loop
	or	edx,edx
	jz	goto_position_ok
	dec	edx
	mov	[caret_position],edx
	mov	[selection_position],edx
      goto_position_ok:
	or	ecx,ecx
	jz	goto_line_ok
	mov	eax,ecx
	call	find_line
	mov	[caret_line],esi
	mov	[selection_line],esi
	mov	[caret_line_number],ecx
	mov	[selection_line_number],ecx
      goto_line_ok:
	call	update_positions
	call	let_caret_appear
	call	update_window
	jmp	main_loop
  search:
	call	find_dialog
	jc	main_loop
	call	find_first
	jc	not_found
	call	show_found_text
	jmp	main_loop
      not_found:
	call	update_screen
	mov	edi,buffer+1000h
	push	edi
	call	get_search_text
	mov	edi,buffer
	mov	esi,_not_found_after
	test	[search_flags],AEFIND_BACKWARD
	jz	make_not_found_message
	mov	esi,_not_found_before
      make_not_found_message:
	mov	ebx,esp
	call	sprintf
	pop	eax
	call	release_search_data
	mov	esi,buffer
	mov	ebx,_find
	movzx	eax,[message_box_colors]
	call	message_box
	jmp	main_loop
      show_found_text:
	mov	eax,[caret_position]
	xchg	eax,[selection_position]
	mov	[caret_position],eax
	call	update_positions
	call	let_caret_appear
	call	update_window
	mov	eax,[caret_position]
	xchg	eax,[selection_position]
	mov	[caret_position],eax
	ret
  replace:
	call	replace_dialog
	jc	main_loop
	mov	[replaces_count],0
	push	edi
	call	find_first
	jc	not_found
	call	store_status_for_undo
      replace_loop:
	test	[command_flags],1
	jz	do_replace
	call	show_found_text
	call	let_caret_appear
	call	update_window
	call	update_screen
	mov	ebx,_replace
	mov	esi,_replace_prompt
	mov	eax,2 shl 24
	mov	ax,[message_box_colors]
	mov	[first_button],_yes
	mov	[second_button],_no
	or	[command_flags],80h
	call	message_box
	and	[command_flags],not 80h
	cmp	eax,1
	jb	replacing_finished
	ja	replace_next
      do_replace:
	call	delete_block
	mov	esi,[esp]
	call	insert_block
	inc	[replaces_count]
      replace_next:
	call	find_next
	jnc	replace_loop
      replacing_finished:
	call	release_search_data
	call	let_caret_appear
	call	update_window
	call	update_screen
	mov	edi,buffer
	mov	esi,_replaces_made
	mov	ebx,replaces_count
	call	sprintf
	mov	esi,buffer
	mov	ebx,_find
	movzx	eax,[message_box_colors]
	call	message_box
	jmp	main_loop
  search_next:
	cmp	[search_data],0
	je	main_loop
	call	find_next
	jc	not_found
	call	show_found_text
	jmp	main_loop
  build_symbols:
	and	[command_flags],not 2
	or	[command_flags],4
	jmp	do_compile
  compile:
	and	[command_flags],not (2 or 4)
	jmp	do_compile
  compile_and_run:
	and	[command_flags],not 4
	or	[command_flags],2
      do_compile:
	push	[editor_memory]
	mov	eax,[main_project_file]
	or	eax,eax
	jz	got_main_file
	call	switch_editor_instance
      got_main_file:
	cmp	[file_path],0
	jne	main_file_path_ok
	call	update_screen
	call	get_saving_path
	jc	main_loop
	call	update_screen
      main_file_path_ok:
	mov	eax,[editor_memory]
	push	eax
	mov	edx,[previous_instance]
	test	edx,edx
	jz	save_all_files
	mov	eax,edx
      find_first_to_save:
	mov	edx,[eax+SEGMENT_HEADER_LENGTH+previous_instance-editor_data]
	or	edx,edx
	jz	save_all_files
	mov	eax,edx
	jmp	find_first_to_save
      save_all_files:
	call	switch_editor_instance
	cmp	[file_path],0
	je	save_next
	mov	eax,[undo_data]
	cmp	eax,[unmodified_state]
	je	save_next
	call	save_file
	jc	main_loop
      save_next:
	mov	eax,[next_instance]
	or	eax,eax
	jnz	save_all_files
	pop	eax
	call	switch_editor_instance
	mov	edi,buffer+3000h
	mov	byte [edi],0
	call	get_current_directory
	mov	esi,[file_path]
	mov	edi,buffer
	mov	ebx,edi
      copy_directory_path:
	lodsb
	or	al,al
	jz	directory_path_ok
	stosb
	cmp	al,'\'
	jne	copy_directory_path
	mov	ebx,edi
	jmp	copy_directory_path
      directory_path_ok:
	mov	byte [ebx],0
	mov	esi,buffer
	call	go_to_directory
	mov	eax,[file_path]
	mov	[input_file],eax
	mov	[symbols_file],0
	test	[command_flags],4
	jz	symbols_file_name_ok
	mov	edi,buffer+2000h
	mov	[symbols_file],edi
	mov	esi,eax
	xor	ebx,ebx
      copy_file_name:
	lodsb
	stosb
	test	al,al
	jz	file_name_copied
	cmp	al,'.'
	jne	copy_file_name
	mov	ebx,edi
	jmp	copy_file_name
      file_name_copied:
	test	ebx,ebx
	jz	attach_fas_extension
	mov	edi,ebx
      attach_fas_extension:
	dec	edi
	mov	eax,'.fas'
	stosd
	xor	al,al
	stosb
      symbols_file_name_ok:
	pop	eax
	call	switch_editor_instance
	mov	cx,1000h
	mov	ah,1
	int	10h
	mov	esi,_compile
	mov	cx,0316h
	mov	ah,[window_colors]
	call	draw_centered_window
	add	edi,2
	mov	[progress_offset],edi
	mov	eax,[memory_limit]
	test	eax,eax
	jnz	allocate_memory
	mov	ax,500h
	mov	edi,buffer
	int	31h
	mov	eax,[edi]
      allocate_memory:
	mov	ecx,eax
	mov	edx,eax
	shr	edx,2
	sub	eax,edx
	mov	[memory_end],eax
	mov	[additional_memory_end],edx
	call	get_memory
	or	eax,eax
	jnz	memory_allocated
	mov	eax,[additional_memory_end]
	shl	eax,1
	cmp	eax,4000h
	jb	not_enough_memory
	jmp	allocate_memory
      get_current_directory:
	mov	ah,19h
	int	21h
	mov	bl,al
	mov	dl,al
	inc	dl
	xor	esi,esi
	mov	ax,7147h
	call	dos_int
	jnc	got_current_directory
	cmp	ax,7100h
	je	get_current_directory_short
      invalid_current_directory:
	stc
	ret
      get_current_directory_short:
	mov	ah,47h
	call	dos_int
	jc	invalid_current_directory
      got_current_directory:
	cmp	byte [buffer],0
	je	drive_prefix
	cmp	byte [buffer+1],':'
	je	copy_current_directory
	cmp	word [buffer],'\\'
	je	copy_current_directory
      drive_prefix:
	mov	al,bl
	add	al,'A'
	mov	ah,':'
	stosw
	mov	al,'\'
	stosb
      copy_current_directory:
	mov	esi,buffer
	call	copy_asciiz
	clc
	ret
      go_to_directory:
	cmp	esi,buffer
	je	directory_path_ready
	mov	edi,buffer
	call	copy_asciiz
	mov	esi,buffer
      directory_path_ready:
	mov	ah,0Eh
	mov	dl,[buffer]
	sub	dl,'A'
	jc	current_directory_ok
	cmp	dl,'Z'-'A'
	jbe	change_current_drive
	sub	dl,'a'-'A'
      change_current_drive:
	int	21h
	xor	dx,dx
	mov	ax,713Bh
	call	dos_int
	cmp	ax,7100h
	jne	current_directory_ok
	mov	ah,3Bh
	call	dos_int
      current_directory_ok:
	ret
      memory_allocated:
	mov	[allocated_memory],ebx
	mov	[memory_start],eax
	add	eax,[memory_end]
	mov	[memory_end],eax
	mov	[additional_memory],eax
	add	[additional_memory_end],eax
	xor	eax,eax
	mov	[output_file],eax
	mov	[display_length],eax
	mov	ax,204h
	mov	bl,9
	int	31h
	mov	dword [keyboard_handler],edx
	mov	word [keyboard_handler+4],cx
	mov	ax,205h
	mov	bl,9
	mov	cx,cs
	mov	edx,aborting_handler
	int	31h
	mov	eax,[fs:6Ch]
	mov	[start_time],eax
	call	preprocessor
	call	draw_progress_segment
	call	parser
	call	draw_progress_segment
	call	assembler
	call	draw_progress_segment
	call	formatter
	call	draw_progress_segment
	mov	ax,205h
	mov	bl,9
	mov	edx,dword [keyboard_handler]
	mov	cx,word [keyboard_handler+4]
	int	31h
	test	[command_flags],2
	jnz	execute
	mov	esi,buffer+3000h
	call	go_to_directory
	call	show_display_buffer
	call	update_screen
	mov	edi,buffer
	movzx	eax,[current_pass]
	inc	eax
	call	number_as_text
	mov	eax,' pas'
	stosd
	mov	eax,'ses,'
	stosd
	mov	al,20h
	stosb
	mov	eax,[fs:6Ch]
	sub	eax,[start_time]
	mov	ebx,100
	mul	ebx
	mov	ebx,182
	div	ebx
	or	eax,eax
	jz	show_bytes_count
	xor	edx,edx
	mov	ebx,10
	div	ebx
	push	edx
	call	number_as_text
	mov	al,'.'
	stosb
	pop	eax
	call	number_as_text
	mov	eax,' sec'
	stosd
	mov	eax,'onds'
	stosd
	mov	ax,', '
	stosw
      show_bytes_count:
	mov	eax,[written_size]
	call	number_as_text
	mov	eax,' byt'
	stosd
	mov	eax,'es.'
	stosd
	mov	ebx,[allocated_memory]
	call	release_memory
	mov	esi,buffer
	mov	ebx,_compile
	movzx	eax,[message_box_colors]
	mov	[first_button],_ok
	mov	[second_button],_get_display
	cmp	[display_length],0
	je	show_compilation_summary
	or	eax,2 shl 24
      show_compilation_summary:
	call	message_box
	cmp	eax,2
	jb	main_loop
	cmp	[clipboard],0
	je	get_display_to_clipboard
	mov	ebx,[clipboard_handle]
	call	release_memory
      get_display_to_clipboard:
	mov	ecx,[display_length]
	inc	ecx
	call	get_memory
	mov	[clipboard_handle],ebx
	mov	[clipboard],eax
	or	eax,eax
	jz	not_enough_memory
	xor	esi,esi
	mov	edi,eax
	mov	ecx,[display_length]
	push	ds
	mov	ds,[low_memory_selector]
	rep	movsb
	pop	ds
	xor	al,al
	stosb
	jmp	main_loop
    execute:
	mov	edx,[output_file]
	call	adapt_path
	mov	ebx,[allocated_memory]
	call	release_memory
	cmp	[output_format],3
	ja	cannot_execute
	call	release_low_memory
	call	switch_to_user_screen
	call	close_video
	mov	edi,buffer+200h
	lea	edx,[edi-buffer]
	mov	ax,0D00h
	stosw
	lea	ebx,[edi-buffer]
	xor	eax,eax
	stosw
	mov	ax,buffer_segment
	shl	eax,16
	mov	ax,dx
	stosd
	xor	eax,eax
	stosd
	stosd
	mov	ax,4B00h
	xor	dx,dx
	call	dos_int
	mov	esi,buffer+3000h
	call	go_to_directory
	call	init_video
	jc	startup_failed
	call	switch_to_ide_screen
	call	get_low_memory
	jmp	main_loop
      cannot_execute:
	mov	esi,buffer+3000h
	call	go_to_directory
	mov	esi,_not_executable
	mov	ebx,_error
	movzx	eax,[error_box_colors]
	call	message_box
	jmp	main_loop
    draw_progress_segment:
	mov	eax,[progress_offset]
	mov	ecx,4
      draw_progress_filler:
	mov	byte [gs:eax],254
	add	eax,2
	loop	draw_progress_filler
	mov	[progress_offset],eax
	ret
    aborting_handler:
	push	eax
	in	al,60h
	cmp	al,1
	jne	no_abort
	mov	dword [esp+4],abort_compiling
	mov	word [esp+4+4],cs
      no_abort:
	pop	eax
	jmp	pword [cs:keyboard_handler]
      abort_compiling:
	cli
	mov	ax,[cs:main_selector]
	mov	esp,stack_top
	mov	ss,ax
	mov	ds,ax
	mov	es,ax
	mov	fs,[bios_selector]
	mov	gs,[video_selector]
	mov	ax,205h
	mov	bl,9
	mov	edx,dword [keyboard_handler]
	mov	cx,word [keyboard_handler+4]
	int	31h
	sti
      discard_keyboard_buffer:
	mov	ah,11h
	int	16h
	jz	keyboard_buffer_ok
	mov	ah,10h
	int	16h
	jmp	discard_keyboard_buffer
      keyboard_buffer_ok:
	mov	ebx,[allocated_memory]
	call	release_memory
	mov	esi,buffer+3000h
	call	go_to_directory
	jmp	main_loop
  assign_to_compiler:
	mov	eax,[editor_memory]
	xchg	eax,[main_project_file]
	cmp	eax,[editor_memory]
	jne	main_loop
	mov	[main_project_file],0
	jmp	main_loop
  calculator:
	call	calculator_window
	jmp	main_loop
  options:
	push	[editor_style]
	call	options_dialog
	pop	eax
	jnc	main_loop
	mov	[editor_style],eax
	jmp	main_loop

  startup_failed:
	mov	esi,_startup_failed
      error_message_loop:
	lodsb
	or	al,al
	jz	error_message_ok
	mov	dl,al
	mov	ah,2
	int	21h
	jmp	error_message_loop
      error_message_ok:
	mov	ax,4C0Fh
	int	21h

  init_video:
	call	check_video_mode
	mov	bx,gs
	movzx	edx,byte [fs:4Ah]
	mov	[screen_width],edx
	shl	edx,1
	mov	[video_pitch],edx
	movzx	eax,byte [fs:84h]
	inc	eax
	mov	[screen_height],eax
	imul	edx,eax
	push	edx
	dec	edx
	shld	ecx,edx,16
	mov	ax,8
	int	31h
	jc	video_init_failed
	pop	ecx
	call	get_memory
	jc	video_init_failed
	mov	[video_storage],eax
	mov	[video_storage_handle],ebx
	clc
	ret
    video_init_failed:
	stc
	ret
    check_video_mode:
	test	byte [fs:65h],110b
	jnz	set_video_mode
	cmp	byte [fs:4Ah],80
	jb	set_video_mode
	ret
    set_video_mode:
	mov	ax,3
	int	10h
	ret
  close_video:
	mov	ebx,[video_storage_handle]
	call	release_memory
	ret
  switch_to_ide_screen:
	call	check_video_mode
	xor	esi,esi
	mov	edi,[video_storage]
	mov	ecx,[video_pitch]
	imul	ecx,[screen_height]
	rep	movs byte [es:edi],[gs:esi]
	mov	ah,3
	xor	bh,bh
	int	10h
	mov	[stored_cursor],cx
	mov	[stored_cursor_position],dx
	mov	ah,0Fh
	int	10h
	mov	[stored_page],bh
	mov	ax,0500h
	int	10h
	mov	al,[fs:65h]
	mov	[stored_mode],al
	mov	ax,1003h
	xor	bx,bx
	int	10h
	mov	eax,[screen_width]
	mov	[window_width],eax
	mov	eax,[screen_height]
	sub	eax,2
	mov	[window_height],eax
	call	update_window
	ret
  switch_to_user_screen:
	push	es gs
	pop	es
	mov	esi,[video_storage]
	xor	edi,edi
	mov	ecx,[video_pitch]
	imul	ecx,[screen_height]
	rep	movs byte [es:edi],[ds:esi]
	mov	ah,1
	mov	cx,[stored_cursor]
	int	10h
	mov	ah,2
	xor	bh,bh
	mov	dx,[stored_cursor_position]
	int	10h
	mov	ah,5
	mov	al,[stored_page]
	int	10h
	mov	ax,1003h
	xor	bh,bh
	mov	bl,[stored_mode]
	shr	bl,5
	and	bl,1
	int	10h
	pop	es
	ret

  create_editor_instance:
	call	flush_editor_data
	mov	esi,[editor_memory]
    find_last_instance:
	mov	eax,[esi+SEGMENT_HEADER_LENGTH+next_instance-editor_data]
	or	eax,eax
	jz	attach_new_instance
	mov	esi,eax
	jmp	find_last_instance
    attach_new_instance:
	push	esi
	call	init_editor_memory
	pop	esi
	jc	not_enough_memory
	mov	eax,[undo_data]
	mov	[unmodified_state],eax
	mov	eax,[editor_memory]
	xchg	eax,[esi+SEGMENT_HEADER_LENGTH+next_instance-editor_data]
	mov	[next_instance],eax
	mov	[previous_instance],esi
	xor	eax,eax
	mov	[file_path],eax
     flush_editor_data:
	mov	edi,[editor_memory]
	test	edi,edi
	jz	flush_ok
	add	edi,SEGMENT_HEADER_LENGTH
	mov	esi,editor_data
	mov	ecx,editor_data_size
	rep	movsb
      flush_ok:
	ret
  switch_editor_instance:
	call	flush_editor_data
	cmp	eax,[editor_memory]
	je	editor_switch_ok
	mov	[editor_memory],eax
	lea	esi,[eax+SEGMENT_HEADER_LENGTH]
	mov	edi,editor_data
	mov	ecx,editor_data_size
	rep	movsb
    editor_switch_ok:
	call	update_positions
	ret
  remove_editor_instance:
	mov	eax,[editor_memory]
	xor	eax,[main_project_file]
	jnz	main_project_file_ok
	mov	[main_project_file],eax
    main_project_file_ok:
	mov	esi,[previous_instance]
	mov	edi,[next_instance]
	mov	eax,edi
	or	edi,edi
	jz	next_instance_links_ok
	mov	[edi+SEGMENT_HEADER_LENGTH+previous_instance-editor_data],esi
    next_instance_links_ok:
	or	esi,esi
	jz	previous_instance_links_ok
	mov	[esi+SEGMENT_HEADER_LENGTH+next_instance-editor_data],edi
	mov	eax,esi
    previous_instance_links_ok:
	push	eax
	call	release_editor_memory
	mov	eax,[file_path]
	or	eax,eax
	jz	file_path_released
	mov	ebx,[file_path_handle]
	call	release_memory
    file_path_released:
	pop	eax
	or	eax,eax
	jz	no_instance_left
	call	switch_editor_instance
	clc
	ret
    no_instance_left:
	stc
	ret

  load_file:
	push	edx [editor_memory]
	call	get_full_pathname
	push	esi
	call	flush_editor_data
	mov	esi,[esp]
	mov	edx,[editor_memory]
      prepare_to_scan_editors:
	mov	eax,[edx+SEGMENT_HEADER_LENGTH+previous_instance-editor_data]
	or	eax,eax
	jz	scan_editors
	mov	edx,eax
	jmp	prepare_to_scan_editors
      scan_editors:
	mov	edi,[edx+SEGMENT_HEADER_LENGTH+file_path-editor_data]
	or	edi,edi
	jz	scan_next_editor
	xor	ecx,ecx
	mov	ebx,lower_case_table
      compare_pathnames:
	mov	al,[esi+ecx]
	xlatb
	mov	ah,al
	mov	al,[edi+ecx]
	xlatb
	cmp	al,ah
	jne	scan_next_editor
	or	al,ah
	jz	file_found
	inc	ecx
	jmp	compare_pathnames
      scan_next_editor:
	mov	edx,[edx+SEGMENT_HEADER_LENGTH+next_instance-editor_data]
	or	edx,edx
	jnz	scan_editors
	mov	eax,[undo_data]
	sub	eax,[unmodified_state]
	or	eax,[file_path]
	jz	open_in_current_instance
	call	create_editor_instance
      open_in_current_instance:
	pop	esi
	call	use_pathname
	mov	edx,[file_path]
	call	open
	jc	load_failed
	xor	edx,edx
	mov	al,2
	call	lseek
	push	eax ebx
	lea	ecx,[eax+1]
	call	get_memory
	or	eax,eax
	jz	not_enough_memory
	mov	esi,eax
	mov	edi,ecx
	pop	ebx
	xor	edx,edx
	xor	al,al
	call	lseek
	pop	ecx
	mov	edx,esi
	mov	byte [edx+ecx],0
	call	read
	jc	load_failed
	call	close
	push	edi
	call	set_text
	pop	ebx
	call	release_memory
	add	esp,8
	ret
      file_found:
	mov	eax,edx
	call	switch_editor_instance
	pop	esi
	add	esp,8
	ret
    load_failed:
	mov	eax,[previous_instance]
	or	eax,[next_instance]
	jnz	cancel_instance
      cancel_path_only:
	xor	ebx,ebx
	xchg	ebx,[file_path]
	call	release_memory
	jmp	editor_cancelled
      cancel_instance:
	mov	eax,[editor_memory]
	cmp	eax,[esp]
	je	cancel_path_only
	call	remove_editor_instance
      editor_cancelled:
	pop	eax
	call	switch_editor_instance
	call	update_screen
	mov	edi,buffer
	mov	esi,_loading_error
	mov	ebx,esp
	call	sprintf
	pop	eax
	mov	esi,buffer
	mov	ebx,_error
	movzx	eax,[error_box_colors]
	call	message_box
	ret
  get_full_pathname:
	call	adapt_path
	sub	edi,buffer
	mov	ax,7160h
	xor	cx,cx
	xor	si,si
	stc
	call	dos_int
	jnc	got_full_pathname
	mov	ah,60h
	call	dos_int
	jc	full_pathname_exit
      got_full_pathname:
	lea	esi,[buffer + edi]
	cmp	word [esi],'\\'
	jne	full_pathname_ok
	cmp	dword [esi+3],'.\A.'
	jne	full_pathname_ok
	mov	al,[esi+2]
	mov	ah,':'
	add	esi,5
	mov	[esi],ax
      full_pathname_ok:
	clc
      full_pathname_exit:
	ret
  use_pathname:
	mov	edi,[file_path]
	or	edi,edi
	jnz	copy_pathname
	mov	ecx,1000h
	push	esi
	call	get_memory
	pop	esi
	or	eax,eax
	jz	not_enough_memory
	mov	edi,eax
	mov	[file_path],edi
	mov	[file_path_handle],ebx
      copy_pathname:
	lodsb
	stosb
	or	al,al
	jnz	copy_pathname
	ret
  save_file:
	mov	edx,[file_path]
	call	create
	jc	file_creation_error
	mov	[file_handle],ebx
	mov	esi,[first_line]
	mov	edi,[line_buffer]
    copy_text:
	mov	ecx,[esi+8]
	lea	eax,[edi+ecx]
	mov	edx,[line_buffer_size]
	shr	edx,1
	sub	eax,edx
	cmp	eax,[line_buffer]
	ja	flush_to_file
	mov	ebp,edi
	xor	edx,edx
	push	ecx
	call	copy_from_line
	pop	ecx
	test	[editor_style],AES_OPTIMALFILL
	jz	line_copied
	cmp	ecx,8
	jb	line_copied
	push	esi edi ecx
	mov	esi,ebp
	mov	edi,[line_buffer]
	mov	eax,[line_buffer_size]
	shr	eax,1
	add	edi,eax
	push	edi
	mov	ecx,[esp+4]
	xor	al,al
	rep	stosb
	mov	ecx,[esp+4]
	mov	edi,[esp]
	call	syntax_proc
	pop	ebx ecx edi
	mov	esi,ebp
	mov	edi,ebp
	sub	ebx,esi
	xor	edx,edx
    optimal_fill:
	lodsb
	cmp	al,20h
	jne	store_character
	cmp	byte [esi-1+ebx],0
	jne	store_character
	mov	eax,esi
	sub	eax,ebp
	test	eax,111b
	jz	store_tab
	inc	edx
	mov	al,20h
	stosb
	loop	optimal_fill
	jmp	optimal_fill_done
    store_tab:
	mov	al,20h
	or	edx,edx
	jz	store_character
	sub	edi,edx
	mov	al,9
    store_character:
	stosb
	xor	edx,edx
	loop	optimal_fill
    optimal_fill_done:
	pop	esi
	jmp	line_copied
    line_copied:
	or	esi,esi
	jz	flush_to_file
	mov	ax,0A0Dh
	stosw
	jmp	copy_text
    flush_to_file:
	push	esi
	mov	edx,[line_buffer]
	mov	ecx,edi
	sub	ecx,edx
	mov	ebx,[file_handle]
	call	write
	jc	file_writing_error
	pop	esi
	mov	edi,[line_buffer]
	or	esi,esi
	jnz	copy_text
	mov	ebx,[file_handle]
	call	close
	mov	eax,[undo_data]
	mov	[unmodified_state],eax
	clc
	ret
    file_writing_error:
	add	esp,4
    file_creation_error:
	call	update_screen
	mov	esi,_saving_error
	mov	ebx,_error
	movzx	eax,[error_box_colors]
	call	message_box
	stc
	ret
  get_saving_path:
	mov	esi,_save_as
	call	file_open_dialog
	jc	saving_aborted
	push	edx
	cmp	byte [edx+ecx-1],'\'
	je	save_in_new_directory
	call	open
	pop	edx
	jc	saving_allowed
	push	edx
	call	close
	call	update_screen
	mov	edi,buffer
	mov	esi,_overwrite_question
	mov	ebx,esp
	call	sprintf
	mov	esi,buffer
	mov	ebx,_save_as
	mov	eax,2 shl 24
	mov	ax,[message_box_colors]
	mov	[first_button],_yes
	mov	[second_button],_no
	call	message_box
	pop	edx
	cmp	eax,1
	jb	saving_aborted
	je	saving_allowed
	call	update_screen
	jmp	get_saving_path
     save_in_new_directory:
	mov	byte [edx+ecx-1],0
	call	update_screen
	mov	edi,buffer
	mov	esi,_directory_question
	mov	ebx,esp
	call	sprintf
	mov	esi,buffer
	mov	ebx,_save_as
	mov	eax,2 shl 24
	mov	ax,[message_box_colors]
	mov	[first_button],_yes
	mov	[second_button],_no
	call	message_box
	pop	esi
	cmp	eax,1
	jb	saving_aborted
	jne	saving_directory_ok
	mov	edi,buffer
	call	copy_asciiz
	mov	ax,7139h
	xor	edx,edx
	call	dos_int
	jnc	new_directory_created
	cmp	ax,7100h
	jne	error_creating_directory
	mov	ah,39h
	call	dos_int
	jc	error_creating_directory
     new_directory_created:
	mov	ax,713Bh
	call	dos_int
	jnc	saving_directory_ok
	cmp	ax,7100h
	jne	error_creating_directory
	mov	ah,3Bh
	call	dos_int
	jc	error_creating_directory
     saving_directory_ok:
	call	update_screen
	jmp	get_saving_path
     error_creating_directory:
	call	update_screen
	mov	esi,_directory_error
	mov	ebx,_error
	movzx	eax,[error_box_colors]
	call	message_box
	jmp	saving_directory_ok
     saving_allowed:
	call	get_full_pathname
	jc	invalid_saving_path
	call	use_pathname
	clc
	ret
     invalid_saving_path:
	call	update_screen
	mov	esi,_invalid_path
	mov	ebx,_error
	movzx	eax,[error_box_colors]
	call	message_box
     saving_aborted:
	stc
	ret

  load_configuration:
	call	load_ini_file
	xor	eax,eax
	mov	[memory_limit],eax
	mov	al,100
	mov	[passes_limit],ax
	mov	ebx,_section_compiler
	mov	esi,_key_compiler_memory
	call	get_ini_int
	jc	memory_setting_ok
	cmp	eax,1 shl (32-10)
	jae	memory_setting_ok
	shl	eax,10
	mov	[memory_limit],eax
      memory_setting_ok:
	mov	esi,_key_compiler_passes
	call	get_ini_int
	jc	passes_setting_ok
	test	eax,eax
	jz	passes_setting_ok
	cmp	eax,10000h
	ja	passes_setting_ok
	mov	[passes_limit],ax
      passes_setting_ok:
	mov	ebx,_section_options
	mov	esi,_key_options_securesel
	call	get_ini_int
	jc	securesel_init_ok
	and	[editor_style],not AES_SECURESEL
	test	eax,eax
	jz	securesel_init_ok
	or	[editor_style],AES_SECURESEL
     securesel_init_ok:
	mov	esi,_key_options_autobrackets
	call	get_ini_int
	jc	autobrackets_init_ok
	and	[editor_style],not AES_AUTOBRACKETS
	test	eax,eax
	jz	autobrackets_init_ok
	or	[editor_style],AES_AUTOBRACKETS
     autobrackets_init_ok:
	mov	esi,_key_options_autoindent
	call	get_ini_int
	jc	autoindent_init_ok
	and	[editor_style],not AES_AUTOINDENT
	test	eax,eax
	jz	autoindent_init_ok
	or	[editor_style],AES_AUTOINDENT
     autoindent_init_ok:
	mov	esi,_key_options_smarttabs
	call	get_ini_int
	jc	smarttabs_init_ok
	and	[editor_style],not AES_SMARTTABS
	test	eax,eax
	jz	smarttabs_init_ok
	or	[editor_style],AES_SMARTTABS
     smarttabs_init_ok:
	mov	esi,_key_options_optimalfill
	call	get_ini_int
	jc	optimalfill_init_ok
	and	[editor_style],not AES_OPTIMALFILL
	test	eax,eax
	jz	optimalfill_init_ok
	or	[editor_style],AES_OPTIMALFILL
     optimalfill_init_ok:
	mov	ebx,_section_colors
	mov	esi,_key_color_text
	call	get_ini_int
	jc	color_text_init_ok
	and	al,0Fh
	and	[text_colors],0F0h
	or	[text_colors],al
     color_text_init_ok:
	mov	esi,_key_color_background
	call	get_ini_int
	jc	color_background_init_ok
	and	al,0Fh
	shl	al,4
	and	[text_colors],0Fh
	or	[text_colors],al
     color_background_init_ok:
	mov	esi,_key_color_seltext
	call	get_ini_int
	jc	color_seltext_init_ok
	and	al,0Fh
	and	[selection_colors],0F0h
	or	[selection_colors],al
     color_seltext_init_ok:
	mov	esi,_key_color_selbackground
	call	get_ini_int
	jc	color_selbackground_init_ok
	and	al,0Fh
	shl	al,4
	and	[selection_colors],0Fh
	or	[selection_colors],al
     color_selbackground_init_ok:
	mov	esi,_key_color_symbols
	call	get_ini_int
	jc	color_symbols_init_ok
	mov	[symbol_color],al
     color_symbols_init_ok:
	mov	esi,_key_color_numbers
	call	get_ini_int
	jc	color_numbers_init_ok
	mov	[number_color],al
     color_numbers_init_ok:
	mov	esi,_key_color_strings
	call	get_ini_int
	jc	color_strings_init_ok
	mov	[string_color],al
     color_strings_init_ok:
	mov	esi,_key_color_comments
	call	get_ini_int
	jc	color_comments_init_ok
	mov	[comment_color],al
     color_comments_init_ok:
	mov	esi,_key_color_statustext
	call	get_ini_int
	jc	color_statustext_init_ok
	and	al,0Fh
	and	[status_colors],0F0h
	or	[status_colors],al
     color_statustext_init_ok:
	mov	esi,_key_color_statusbackground
	call	get_ini_int
	jc	color_statusbackground_init_ok
	and	al,0Fh
	shl	al,4
	and	[status_colors],0Fh
	or	[status_colors],al
     color_statusbackground_init_ok:
	mov	esi,_key_color_wintext
	call	get_ini_int
	jc	color_wintext_init_ok
	and	al,0Fh
	and	[window_colors],0F0h
	or	[window_colors],al
     color_wintext_init_ok:
	mov	esi,_key_color_winbackground
	call	get_ini_int
	jc	color_winbackground_init_ok
	and	al,0Fh
	shl	al,4
	and	[window_colors],0Fh
	or	[window_colors],al
     color_winbackground_init_ok:
	mov	esi,_key_color_msgtext
	call	get_ini_int
	jc	color_msgtext_init_ok
	and	al,0Fh
	and	byte [message_box_colors+1],0F0h
	or	byte [message_box_colors+1],al
     color_msgtext_init_ok:
	mov	esi,_key_color_msgbackground
	call	get_ini_int
	jc	color_msgbackground_init_ok
	and	al,0Fh
	shl	al,4
	and	byte [message_box_colors+1],0Fh
	or	byte [message_box_colors+1],al
     color_msgbackground_init_ok:
	mov	esi,_key_color_msgseltext
	call	get_ini_int
	jc	color_msgseltext_init_ok
	and	al,0Fh
	and	byte [message_box_colors],0F0h
	or	byte [message_box_colors],al
     color_msgseltext_init_ok:
	mov	esi,_key_color_msgselbackground
	call	get_ini_int
	jc	color_msgselbackground_init_ok
	and	al,0Fh
	shl	al,4
	and	byte [message_box_colors],0Fh
	or	byte [message_box_colors],al
     color_msgselbackground_init_ok:
	mov	esi,_key_color_errtext
	call	get_ini_int
	jc	color_errtext_init_ok
	and	al,0Fh
	and	byte [error_box_colors+1],0F0h
	or	byte [error_box_colors+1],al
     color_errtext_init_ok:
	mov	esi,_key_color_errbackground
	call	get_ini_int
	jc	color_errbackground_init_ok
	and	al,0Fh
	shl	al,4
	and	byte [error_box_colors+1],0Fh
	or	byte [error_box_colors+1],al
     color_errbackground_init_ok:
	mov	esi,_key_color_errseltext
	call	get_ini_int
	jc	color_errseltext_init_ok
	and	al,0Fh
	and	byte [error_box_colors],0F0h
	or	byte [error_box_colors],al
     color_errseltext_init_ok:
	mov	esi,_key_color_errselbackground
	call	get_ini_int
	jc	color_errselbackground_init_ok
	and	al,0Fh
	shl	al,4
	and	byte [error_box_colors],0Fh
	or	byte [error_box_colors],al
     color_errselbackground_init_ok:
	mov	esi,_key_color_boxtext
	call	get_ini_int
	jc	color_boxtext_init_ok
	and	al,0Fh
	and	[box_colors],0F0h
	or	[box_colors],al
     color_boxtext_init_ok:
	mov	esi,_key_color_boxbackground
	call	get_ini_int
	jc	color_boxbackground_init_ok
	and	al,0Fh
	shl	al,4
	and	[box_colors],0Fh
	or	[box_colors],al
     color_boxbackground_init_ok:
	mov	esi,_key_color_boxseltext
	call	get_ini_int
	jc	color_boxseltext_init_ok
	and	al,0Fh
	and	byte [box_selection_colors],0F0h
	or	byte [box_selection_colors],al
     color_boxseltext_init_ok:
	mov	esi,_key_color_boxselbackground
	call	get_ini_int
	jc	color_boxselbackground_init_ok
	and	al,0Fh
	shl	al,4
	and	byte [box_selection_colors],0Fh
	or	byte [box_selection_colors],al
     color_boxselbackground_init_ok:
	ret
  load_ini_file:
	cmp	[ini_data],0
	je	open_ini_file
	mov	ebx,[ini_data_handle]
	call	release_memory
      open_ini_file:
	mov	edx,ini_path
	call	open
	jc	no_ini_file
	xor	edx,edx
	mov	al,2
	call	lseek
	push	eax
	xor	edx,edx
	xor	al,al
	call	lseek
	mov	ecx,[esp]
	add	ecx,800h
	push	ebx
	call	get_memory
	mov	[ini_data],eax
	mov	[ini_data_handle],ebx
	pop	ebx ecx
	test	eax,eax
	jz	ini_loaded
	mov	edx,eax
	mov	byte [edx+ecx],1Ah
	mov	[ini_data_length],ecx
	call	read
	call	close
	ret
      no_ini_file:
	mov	ecx,800h
	call	get_memory
	mov	[ini_data],eax
	test	eax,eax
	jz	ini_loaded
	mov	byte [eax],1Ah
	mov	[ini_data_length],0
      ini_loaded:
	ret
  get_ini_value:
	mov	edi,esi
	mov	esi,[ini_data]
	test	esi,esi
	jz	ini_value_not_found
	call	find_ini_block
	jc	ini_value_not_found
	call	find_ini_value
	ret
     ini_value_not_found:
	stc
	ret
     find_ini_block:
	lodsb
	cmp	al,20h
	je	find_ini_block
	cmp	al,9
	je	find_ini_block
	cmp	al,'['
	jne	look_for_ini_block_in_next_line
     find_block_name:
	lodsb
	cmp	al,20h
	je	find_block_name
	cmp	al,9
	je	find_block_name
	dec	esi
	mov	edx,ebx
     compare_block_name_char:
	lodsb
	mov	ah,[edx]
	inc	edx
	cmp	al,']'
	je	end_of_block_name
	cmp	al,20h
	je	end_of_block_name
	cmp	al,9
	je	end_of_block_name
	cmp	al,1Ah
	je	end_of_block_name
	cmp	al,0Dh
	je	end_of_block_name
	cmp	al,0Ah
	je	end_of_block_name
	or	ah,ah
	jz	look_for_ini_block_in_next_line
	sub	ah,al
	jz	compare_block_name_char
	jns	block_name_char_case_insensitive
	neg	ah
	sub	al,20h
     block_name_char_case_insensitive:
	cmp	ah,20h
	jne	look_for_ini_block_in_next_line
	cmp	al,41h
	jb	look_for_ini_block_in_next_line
	cmp	al,5Ah
	jna	compare_block_name_char
     look_for_ini_block_in_next_line:
	dec	esi
	call	find_next_ini_line
	cmp	byte [esi],1Ah
	jne	find_ini_block
	stc
	ret
     end_of_block_name:
	test	ah,ah
	jnz	look_for_ini_block_in_next_line
	cmp	al,']'
	je	end_of_block_name_ok
	cmp	al,20h
	je	find_block_name_closing_bracket
	cmp	al,9
	jne	look_for_ini_block_in_next_line
     find_block_name_closing_bracket:
	lodsb
	jmp	end_of_block_name
     end_of_block_name_ok:
	call	find_next_ini_line
	clc
	ret
     find_next_ini_line:
	lodsb
	cmp	al,0Dh
	je	line_ending
	cmp	al,0Ah
	je	line_ending
	cmp	al,1Ah
	jne	find_next_ini_line
	dec	esi
	ret
     line_ending:
	lodsb
	cmp	al,0Dh
	je	line_ending
	cmp	al,0Ah
	je	line_ending
	dec	esi
	ret
     find_ini_value:
	lodsb
	cmp	al,20h
	je	find_ini_value
	cmp	al,9
	je	find_ini_value
	cmp	al,0Dh
	je	next_ini_value
	cmp	al,0Ah
	je	next_ini_value
	dec	esi
	cmp	al,1Ah
	je	no_ini_value_found
	cmp	al,'['
	je	no_ini_value_found
	mov	edx,edi
     compare_value_name_char:
	lodsb
	mov	ah,[edx]
	inc	edx
	cmp	al,'='
	je	end_of_value_name
	cmp	al,20h
	je	end_of_value_name
	cmp	al,9
	je	end_of_value_name
	cmp	al,1Ah
	je	end_of_value_name
	cmp	al,0Dh
	je	end_of_value_name
	cmp	al,0Ah
	je	end_of_value_name
	or	ah,ah
	jz	next_ini_value
	sub	ah,al
	jz	compare_value_name_char
	jns	value_name_char_case_insensitive
	neg	ah
	sub	al,20h
     value_name_char_case_insensitive:
	cmp	ah,20h
	jne	next_ini_value
	cmp	al,41h
	jb	next_ini_value
	cmp	al,5Ah
	jna	compare_value_name_char
     next_ini_value:
	dec	esi
	call	find_next_ini_line
	cmp	byte [esi],1Ah
	jne	find_ini_value
     no_ini_value_found:
	stc
	ret
     end_of_value_name:
	test	ah,ah
	jnz	next_ini_value
	cmp	al,'='
	je	ini_value_found
	cmp	al,20h
	je	find_ini_value_start
	cmp	al,9
	jne	next_ini_value
     find_ini_value_start:
	lodsb
	jmp	end_of_value_name
     ini_value_found:
	xor	ecx,ecx
     find_value_length:
	cmp	byte [esi+ecx],0Dh
	je	value_length_found
	cmp	byte [esi+ecx],0Ah
	je	value_length_found
	cmp	byte [esi+ecx],1Ah
	je	value_length_found
	inc	ecx
	jmp	find_value_length
     value_length_found:
	clc
	ret
  get_ini_int:
	call	get_ini_value
	jc	no_ini_int
	push	ebx
	call	atoi
	pop	ebx
	ret
     no_ini_int:
	stc
	ret
  atoi:
	lodsb
	cmp	al,20h
	je	atoi
	cmp	al,9
	je	atoi
	mov	bl,al
	xor	eax,eax
	xor	edx,edx
	cmp	bl,'-'
	je	atoi_digit
	cmp	bl,'+'
	je	atoi_digit
	dec	esi
      atoi_digit:
	mov	dl,[esi]
	sub	dl,30h
	jc	atoi_done
	cmp	dl,9
	ja	atoi_done
	mov	ecx,eax
	shl	ecx,1
	jc	atoi_overflow
	shl	ecx,1
	jc	atoi_overflow
	add	eax,ecx
	shl	eax,1
	jc	atoi_overflow
	js	atoi_overflow
	add	eax,edx
	jc	atoi_overflow
	inc	esi
	jmp	atoi_digit
      atoi_overflow:
	stc
	ret
      atoi_done:
	cmp	bl,'-'
	jne	atoi_sign_ok
	neg	eax
      atoi_sign_ok:
	clc
	ret
  update_ini_value:
	mov	ebp,edx
	mov	esi,[ini_data]
	test	esi,esi
	jz	cannot_update_ini
	call	find_ini_block
	jc	create_ini_block
	call	find_ini_value
	jc	create_ini_value
	mov	edi,esi
	mov	esi,ebp
	jecxz	place_for_ini_value_exhausted
      copy_value_to_ini:
	lodsb
	test	al,al
	jz	shift_rest_of_ini_down
	stosb
	loop	copy_value_to_ini
      place_for_ini_value_exhausted:
	cmp	byte [esi],0
	jne	shift_rest_of_ini_up
	ret
      shift_rest_of_ini_down:
	lea	esi,[edi+ecx]
	neg	ecx
	xchg	ecx,[ini_data_length]
	add	[ini_data_length],ecx
	inc	ecx
	add	ecx,[ini_data]
	sub	ecx,esi
	rep	movsb
	ret
      shift_rest_of_ini_up:
	push	esi edi
	mov	edi,esi
	xor	al,al
	or	ecx,-1
	repne	scasb
	neg	ecx
	sub	ecx,2
	mov	esi,[ini_data]
	add	esi,[ini_data_length]
	mov	edi,esi
	add	edi,ecx
	add	[ini_data_length],ecx
	mov	ebp,ecx
	mov	ecx,esi
	sub	ecx,[esp]
	inc	ecx
	std
	rep	movsb
	cld
	pop	edi esi
	mov	ecx,ebp
	rep	movsb
	ret
      cannot_update_ini:
	ret
      create_ini_block:
	push	edi
	mov	edi,[ini_data]
	mov	ecx,[ini_data_length]
	add	edi,ecx
	jecxz	make_ini_block_header
	mov	ax,0A0Dh
	stosw
      make_ini_block_header:
	mov	al,'['
	stosb
	mov	esi,ebx
	call	copy_str
	mov	al,']'
	stosb
	mov	ax,0A0Dh
	stosw
	pop	esi
      append_ini_value:
	call	copy_str
	mov	al,'='
	stosb
	mov	esi,ebp
	call	copy_str
	mov	ax,0A0Dh
	stosw
	mov	ecx,edi
	sub	ecx,[ini_data]
	mov	[ini_data_length],ecx
	mov	al,1Ah
	stosb
	ret
      copy_str:
	lodsb
	test	al,al
	jz	str_copied
	stosb
	jmp	copy_str
      str_copied:
	ret
      create_ini_value:
	cmp	esi,[ini_data]
	je	ini_value_placement_ok
	dec	esi
	mov	al,[esi]
	cmp	al,20h
	je	create_ini_value
	cmp	al,9
	je	create_ini_value
	cmp	al,0Dh
	je	create_ini_value
	cmp	al,0Ah
	je	create_ini_value
	inc	esi
      find_place_for_ini_value:
	mov	al,[esi]
	lodsb
	cmp	al,0Ah
	je	ini_value_placement_ok
	cmp	al,1Ah
	je	value_at_end_of_ini
	cmp	al,0Dh
	jne	find_place_for_ini_value
	cmp	byte [esi],0Ah
	jne	ini_value_placement_ok
	inc	esi
      ini_value_placement_ok:
	push	edi esi
	xor	al,al
	or	ecx,-1
	repne	scasb
	mov	edi,ebp
	repne	scasb
	neg	ecx
	mov	edi,ecx
	mov	ecx,esi
	neg	ecx
	mov	esi,[ini_data]
	add	esi,[ini_data_length]
	add	[ini_data_length],edi
	add	edi,esi
	add	ecx,esi
	inc	ecx
	std
	rep	movsb
	cld
	pop	edi esi
	call	copy_str
	mov	al,'='
	stosb
	mov	esi,ebp
	call	copy_str
	mov	ax,0A0Dh
	stosw
	ret
      value_at_end_of_ini:
	xchg	esi,edi
	mov	ax,0A0Dh
	stosw
	jmp	append_ini_value

  shutdown:
	call	switch_to_user_screen
	call	load_ini_file
	cmp	[ini_data],0
	je	exit
	mov	ebx,_section_options
	mov	edi,_key_options_securesel
	test	[editor_style],AES_SECURESEL
	setnz	al
	add	al,'0'
	mov	edx,line_buffer
	mov	byte [edx+1],0
	mov	[edx],al
	call	update_ini_value
	mov	edi,_key_options_autobrackets
	test	[editor_style],AES_AUTOBRACKETS
	setnz	al
	add	al,'0'
	mov	edx,line_buffer
	mov	[edx],al
	call	update_ini_value
	mov	edi,_key_options_autoindent
	test	[editor_style],AES_AUTOINDENT
	setnz	al
	add	al,'0'
	mov	edx,line_buffer
	mov	[edx],al
	call	update_ini_value
	mov	edi,_key_options_smarttabs
	test	[editor_style],AES_SMARTTABS
	setnz	al
	add	al,'0'
	mov	edx,line_buffer
	mov	[edx],al
	call	update_ini_value
	mov	edi,_key_options_optimalfill
	test	[editor_style],AES_OPTIMALFILL
	setnz	al
	add	al,'0'
	mov	edx,line_buffer
	mov	[edx],al
	call	update_ini_value
	mov	edx,ini_path
	call	create
	jc	exit
	mov	edx,[ini_data]
	mov	ecx,[ini_data_length]
	call	write
	call	close
      exit:
	mov	ax,4C00h
	int	21h

; Positioning

  update_positions:
	mov	eax,[screen_width]
	mov	[window_width],eax
	mov	eax,[screen_height]
	sub	eax,2
	mov	[window_height],eax
	call	update_window
	ret
  update_cursor:
	xor	bh,bh
	mov	edx,[caret_position]
	sub	edx,[window_position]
	jc	cursor_out_of_sight
	cmp	edx,[window_width]
	jae	cursor_out_of_sight
	mov	eax,[caret_line_number]
	sub	eax,[window_line_number]
	jc	cursor_out_of_sight
	cmp	eax,[window_height]
	jae	cursor_out_of_sight
	inc	al
	mov	dh,al
	mov	ah,2
	int	10h
	test	[editor_mode],AEMODE_OVERWRITE
	jnz	block_cursor
	mov	ah,1
	mov	cx,0D0Eh
	int	10h
	ret
    block_cursor:
	mov	ah,1
	mov	cx,000Fh
	int	10h
	ret
    cursor_out_of_sight:
	mov	ah,1
	mov	cx,1000h
	int	10h
	ret

; Text drawing

  update_screen:
	call	update_title_bar
	mov	eax,[peak_line_length]
	xor	edx,edx
	mov	ebx,SEGMENT_DATA_LENGTH
	div	ebx
	inc	eax
	mul	ebx
	shl	eax,1
	mov	ecx,eax
	cmp	[line_buffer],0
	je	line_buffer_reallocate
	cmp	ecx,[line_buffer_size]
	jbe	line_buffer_ok
	mov	[line_buffer],0
	push	ecx
	mov	ebx,[line_buffer_handle]
	call	release_memory
	pop	ecx
    line_buffer_reallocate:
	call	get_memory
	or	eax,eax
	jz	memory_shortage
	mov	[line_buffer],eax
	mov	[line_buffer_handle],ebx
    line_buffer_ok:
	mov	esi,[window_line]
	mov	edx,[window_line_number]
	mov	eax,[video_pitch]
	mov	[screen_offset],eax
	mov	edi,[line_buffer]
    prepare_line:
	add	esi,SEGMENT_HEADER_LENGTH
	mov	ecx,SEGMENT_DATA_LENGTH
	rep	movsb
	mov	esi,[esi-SEGMENT_LENGTH]
	btr	esi,0
	jc	prepare_line
	push	esi edx
	mov	ecx,edi
	mov	esi,[line_buffer]
	sub	ecx,esi
	push	ecx
	mov	al,[text_colors]
	and	al,0Fh
	rep	stosb
	mov	esi,[line_buffer]
	mov	ecx,[esp]
	lea	edi,[esi+ecx]
	call	syntax_proc
    line_prepared:
	mov	edi,screen_row_buffer
	mov	ecx,[window_width]
	mov	al,20h
	mov	ah,[text_colors]
	rep	stosw
	pop	ecx
	mov	esi,[line_buffer]
	lea	ebx,[esi+ecx]
	add	esi,[window_position]
	add	ebx,[window_position]
	sub	ecx,[window_position]
	jbe	text_drawing_ok
	mov	edi,screen_row_buffer
	cmp	ecx,[window_width]
	jbe	draw_text
	mov	ecx,[window_width]
    draw_text:
	movsb
	mov	al,[text_colors]
	and	al,0F0h
	or	al,[ebx]
	stosb
	inc	ebx
	loop	draw_text
    text_drawing_ok:
	mov	edi,screen_row_buffer
	cmp	[selection_line],0
	je	selection_marked
	mov	eax,[selection_line_number]
	cmp	eax,[caret_line_number]
	jne	mark_multiline_selection
	cmp	eax,[esp]
	jne	selection_marked
    mark_simple_selection:
	mov	eax,[selection_position]
	mov	ecx,[caret_position]
	cmp	eax,ecx
	jbe	simple_selection_boundaries_ok
	xchg	eax,ecx
    simple_selection_boundaries_ok:
	sub	ecx,[window_position]
	jbe	selection_marked
	sub	eax,[window_position]
	jae	simple_selection_start_ok
	xor	eax,eax
    simple_selection_start_ok:
	cmp	ecx,[window_width]
	jbe	simple_selection_length_ok
	mov	ecx,[window_width]
    simple_selection_length_ok:
	sub	ecx,eax
	jbe	selection_marked
	lea	edi,[screen_row_buffer+eax*2]
    draw_selection:
	inc	edi
	mov	al,[selection_colors]
	stosb
	loop	draw_selection
	jmp	selection_marked
    mark_multiline_selection:
	test	[editor_mode],AEMODE_VERTICALSEL
	jnz	mark_vertical_selection
	mov	eax,[selection_line_number]
	mov	ebx,[selection_position]
	mov	edx,[caret_line_number]
	mov	ebp,[caret_position]
	cmp	eax,edx
	jbe	multiline_selection_boundaries_ok
	xchg	eax,edx
	xchg	ebx,ebp
    multiline_selection_boundaries_ok:
	mov	edi,screen_row_buffer
	mov	ecx,[window_width]
	cmp	eax,[esp]
	ja	selection_marked
	je	mark_selection_start
	cmp	edx,[esp]
	ja	draw_selection
	jb	selection_marked
    mark_selection_end:
	cmp	ebp,[window_position]
	jbe	selection_marked
	sub	ebp,[window_position]
	cmp	ecx,ebp
	jbe	draw_selection
	mov	ecx,ebp
	jmp	draw_selection
    mark_selection_start:
	sub	ebx,[window_position]
	jbe	draw_selection
	sub	ecx,ebx
	jbe	selection_marked
	lea	edi,[edi+ebx*2]
	jmp	draw_selection
    mark_vertical_selection:
	mov	eax,[selection_line_number]
	mov	edx,[caret_line_number]
	sub	eax,[esp]
	jz	mark_simple_selection
	sub	edx,[esp]
	jz	mark_simple_selection
	xor	eax,edx
	js	mark_simple_selection
    selection_marked:
	push	es gs
	pop	es
	mov	esi,screen_row_buffer
	mov	edi,[screen_offset]
	mov	ecx,[window_width]
	shr	ecx,1
	rep	movsd
	setc	cl
	rep	movsw
	mov	eax,[window_width]
	shl	eax,1
	sub	edi,eax
	add	edi,[video_pitch]
	mov	[screen_offset],edi
	pop	es
	pop	edx esi
	inc	edx
	mov	eax,edx
	sub	eax,[window_line_number]
	cmp	eax,[window_height]
	jae	screen_ok
	mov	edi,[line_buffer]
	or	esi,esi
	jnz	prepare_line
	push	esi edx
	push	[window_position]
	jmp	line_prepared
    screen_ok:
	call	update_status_bar
	ret

  syntax_proc:
	mov	ebx,characters
	xor	edx,edx
    scan_syntax:
	lodsb
    check_character:
	cmp	al,20h
	je	syntax_space
	cmp	al,3Bh
	je	syntax_comment
	mov	ah,al
	xlatb
	or	al,al
	jz	syntax_symbol
	or	edx,edx
	jnz	syntax_neutral
	cmp	ah,27h
	je	syntax_string
	cmp	ah,22h
	je	syntax_string
	cmp	ah,24h
	je	syntax_pascal_hex
	cmp	ah,39h
	ja	syntax_neutral
	cmp	ah,30h
	jae	syntax_number
    syntax_neutral:
	or	edx,-1
	inc	edi
	loop	scan_syntax
	jmp	syntax_done
    syntax_space:
	xor	edx,edx
	inc	edi
	loop	scan_syntax
	jmp	syntax_done
    syntax_symbol:
	mov	al,[symbol_color]
	stosb
	xor	edx,edx
	loop	scan_syntax
	jmp	syntax_done
    syntax_pascal_hex:
	cmp	ecx,1
	je	syntax_neutral
	mov	al,[esi]
	mov	ah,al
	xlatb
	or	al,al
	jz	syntax_neutral
	cmp	ah,24h
	jne	syntax_number
	cmp	ecx,2
	je	syntax_neutral
	mov	al,[esi+1]
	xlatb
	or	al,al
	jz	syntax_neutral
    syntax_number:
	mov	al,[number_color]
	stosb
	loop	number_character
	jmp	syntax_done
    number_character:
	lodsb
	mov	ah,al
	xlatb
	xchg	al,ah
	or	ah,ah
	jz	check_character
	cmp	al,20h
	je	check_character
	cmp	al,3Bh
	je	check_character
	mov	al,[number_color]
	stosb
	loop	number_character
	jmp	syntax_done
    syntax_string:
	mov	al,[string_color]
	stosb
	dec	ecx
	jz	syntax_done
	lodsb
	cmp	al,ah
	jne	syntax_string
	mov	al,[string_color]
	stosb
	dec	ecx
	jz	syntax_done
	lodsb
	cmp	al,ah
	je	syntax_string
	xor	edx,edx
	jmp	check_character
    syntax_comment:
	mov	al,[comment_color]
	stosb
	loop	syntax_comment
    syntax_done:
	ret

; Status drawing

  update_status_bar:
	mov	edi,screen_row_buffer
	mov	al,20h
	mov	ecx,[screen_width]
	rep	stosb
	mov	edi,screen_row_buffer+256
	mov	eax,'Row '
	stosd
	mov	eax,[caret_line_number]
	call	number_as_text
	mov	al,'/'
	stosb
	mov	eax,[lines_count]
	call	number_as_text
	mov	eax,', Co'
	stosd
	mov	eax,'lumn'
	stosd
	mov	al,' '
	stosb
	mov	eax,[caret_position]
	inc	eax
	call	number_as_text
	mov	al,'/'
	stosb
	mov	eax,[maximum_position]
	inc	eax
	call	number_as_text
	mov	ecx,edi
	mov	esi,screen_row_buffer+256
	sub	ecx,esi
	mov	eax,[screen_width]
	lea	edi,[screen_row_buffer+eax-1]
	sub	edi,ecx
	mov	byte [edi-2],0B3h
	lea	ebx,[edi-11]
	rep	movsb
	mov	edi,ebx
	sub	ebx,2
	mov	byte [ebx],0B3h
	push	ebx
	mov	eax,[undo_data]
	cmp	eax,[unmodified_state]
	je	modified_status_ok
	mov	eax,'Modi'
	stosd
	mov	eax,'fied'
	stosd
     modified_status_ok:
	mov	edi,screen_row_buffer+1
	xor	eax,eax
	mov	edx,[previous_instance]
     count_preceding_instances:
	inc	eax
	or	edx,edx
	jz	preceding_instances_count_ok
	mov	edx,[edx+SEGMENT_HEADER_LENGTH+previous_instance-editor_data]
	jmp	count_preceding_instances
     preceding_instances_count_ok:
	push	eax
	call	number_as_text
	mov	al,'/'
	stosb
	pop	eax
	mov	edx,[next_instance]
     count_following_instances:
	or	edx,edx
	jz	following_instances_count_ok
	inc	eax
	mov	edx,[edx+SEGMENT_HEADER_LENGTH+next_instance-editor_data]
	jmp	count_following_instances
     following_instances_count_ok:
	call	number_as_text
	inc	edi
	mov	al,'-'
	stosb
	inc	edi
	pop	ecx
	sub	ecx,edi
	mov	esi,[file_path]
	call	get_file_title
      print_file_title:
	lodsb
	or	al,al
	jz	editor_title_ok
	stosb
	loop	print_file_title
      editor_title_ok:
	push	es gs
	pop	es
	mov	edi,[video_pitch]
	mov	eax,[screen_height]
	dec	eax
	imul	edi,eax
	mov	esi,screen_row_buffer
	mov	ecx,[screen_width]
	mov	ah,[status_colors]
     draw_status_bar:
	lodsb
	stosw
	loop	draw_status_bar
	pop	es
	ret
     get_file_title:
	or	esi,esi
	jz	untitled
	mov	ebx,esi
      find_file_name:
	lodsb
	or	al,al
	jz	file_title_ok
	cmp	al,'\'
	jne	find_file_name
	mov	ebx,esi
	jmp	find_file_name
      file_title_ok:
	mov	esi,ebx
	ret
      untitled:
	mov	esi,_untitled
	ret
  update_title_bar:
	mov	edi,screen_row_buffer
	mov	al,20h
	mov	ecx,[screen_width]
	sub	ecx,10+1
	rep	stosb
	mov	al,0B3h
	stosb
	mov	esi,_caption
	mov	edi,screen_row_buffer+1
     draw_caption:
	lodsb
	or	al,al
	jz	caption_ok
	stosb
	jmp	draw_caption
     caption_ok:
	mov	edx,[main_project_file]
	or	edx,edx
	jz	main_file_title_ok
	mov	al,20h
	stosb
	mov	al,'-'
	stosb
	mov	al,20h
	stosb
	mov	esi,[file_path]
	cmp	edx,[editor_memory]
	je	get_main_file_title
	mov	esi,[edx+SEGMENT_HEADER_LENGTH+file_path-editor_data]
     get_main_file_title:
	call	get_file_title
	mov	ecx,[screen_width]
	add	ecx,screen_row_buffer-14
	sub	ecx,edi
     print_main_file_title:
	lodsb
	or	al,al
	jz	main_file_title_ok
	stosb
	loop	print_main_file_title
     main_file_title_ok:
	push	es gs
	pop	es
	xor	edi,edi
	mov	esi,screen_row_buffer
	mov	ecx,[screen_width]
	sub	ecx,10
	mov	ah,[status_colors]
     draw_title_bar:
	lodsb
	stosw
	loop	draw_title_bar
	pop	es
	call	update_clock
	ret
  update_clock:
	mov	edi,[screen_width]
	mov	ecx,10
	sub	edi,ecx
	shl	edi,1
	mov	al,[status_colors]
     prepare_clock_colors:
	mov	[gs:edi+(ecx-1)*2+1],al
	loop	prepare_clock_colors
	mov	ah,2Ch
	int	21h
	mov	[gs:edi],byte 20h
	mov	al,ch
	aam
	add	ax,'00'
	mov	[gs:edi+1*2],ah
	mov	[gs:edi+2*2],al
	mov	[gs:edi+3*2],byte ':'
	mov	al,cl
	aam
	add	ax,'00'
	mov	[gs:edi+4*2],ah
	mov	[gs:edi+5*2],al
	mov	[gs:edi+6*2],byte ':'
	mov	al,dh
	aam
	add	ax,'00'
	mov	[gs:edi+7*2],ah
	mov	[gs:edi+8*2],al
	mov	[gs:edi+9*2],byte 20h
	ret
  wait_for_input:
	call	update_clock
	mov	ah,11h
	int	16h
	jz	wait_for_input
	mov	ah,10h
	int	16h
	ret

  number_as_text:
	push	ebx
	mov	ecx,1000000000
	xor	edx,edx
	xor	bl,bl
      number_loop:
	div	ecx
	push	edx
	cmp	ecx,1
	je	store_digit
	or	bl,bl
	jnz	store_digit
	or	al,al
	jz	digit_ok
	not	bl
      store_digit:
	add	al,'0'
	stosb
      digit_ok:
	mov	eax,ecx
	xor	edx,edx
	mov	ecx,10
	div	ecx
	mov	ecx,eax
	pop	eax
	or	ecx,ecx
	jnz	number_loop
	pop	ebx
	ret
  sprintf:
	lodsb
	cmp	al,'%'
	je	format_parameter
	stosb
	or	al,al
	jnz	sprintf
	ret
    format_parameter:
	lodsb
	mov	edx,[ebx]
	add	ebx,4
	cmp	al,'s'
	je	insert_string
	cmp	al,'d'
	je	insert_number
	or	al,al
	jnz	sprintf
	dec	esi
	jmp	sprintf
    insert_number:
	push	esi
	mov	eax,edx
	call	number_as_text
	pop	esi
	jmp	sprintf
    insert_string:
	push	esi
	mov	esi,edx
    string_insertion_loop:
	lodsb
	or	al,al
	jz	string_insertion_ok
	stosb
	jmp	string_insertion_loop
    string_insertion_ok:
	pop	esi
	jmp	sprintf

; Windows

  message_box:
	push	eax ebx
	xor	ebp,ebp
	mov	edi,buffer+200h
	mov	dl,[esp+4+3]
	or	dl,dl
	jnz	calculate_buttons_width
	mov	dl,1
	mov	[first_button],_ok
    calculate_buttons_width:
	mov	[buttons_width],0
	mov	eax,[first_button]
	call	add_button_width
	dec	dl
	jz	buttons_width_ok
	add	[buttons_width],2
	mov	eax,[second_button]
	call	add_button_width
	jmp	buttons_width_ok
    add_button_width:
	push	edi
	mov	edi,eax
	xor	al,al
	or	ecx,-1
	repne	scasb
	neg	cl
	add	cl,6-2
	add	[buttons_width],cl
	pop	edi
	ret
    buttons_width_ok:
	mov	al,[buttons_width]
	mov	[message_width],al
    start_message_line:
	mov	ebx,edi
	mov	edx,edi
	mov	ecx,[screen_width]
	sub	ecx,14
	mov	eax,[screen_height]
	sub	eax,7
	inc	ebp
	cmp	ebp,eax
	jae	message_prepared
    copy_message:
	lodsb
	stosb
	cmp	al,20h
	jne	message_character_ok
	mov	edx,edi
    message_character_ok:
	cmp	byte [esi],0
	je	message_prepared
	loop	copy_message
	cmp	edx,ebx
	je	split_word
	lea	eax,[edx-1]
	mov	ecx,[screen_height]
	sub	ecx,7
	inc	ebp
	cmp	ebp,ecx
	je	cut_message
	mov	byte [eax],0Ah
	sub	eax,ebx
	mov	ebx,edx
	mov	ecx,[screen_width]
	lea	ecx,[ecx-14+ebx]
	sub	ecx,edi
	cmp	al,[message_width]
	jbe	copy_message
	mov	[message_width],al
	jmp	copy_message
    cut_message:
	mov	edi,eax
	jmp	message_prepared
    split_word:
	mov	eax,[screen_width]
	sub	eax,14
	mov	[message_width],al
	mov	al,0Ah
	stosb
	jmp	start_message_line
    message_prepared:
	mov	eax,edi
	sub	eax,ebx
	cmp	al,[message_width]
	jbe	message_width_ok
	mov	[message_width],al
    message_width_ok:
	xor	al,al
	stosb
	mov	ecx,ebp
	mov	ch,cl
	add	ch,6
	mov	cl,[message_width]
	add	cl,8
	pop	esi
	mov	ah,[esp+1]
	call	draw_centered_window
	mov	esi,buffer+200h
	add	edi,2*2
    draw_message:
	xor	ecx,ecx
	add	edi,[video_pitch]
    draw_message_row:
	lodsb
	or	al,al
	jz	message_drawn
	cmp	al,0Ah
	je	draw_message
	mov	byte [gs:edi+ecx*2],al
	inc	ecx
	jmp	draw_message_row
    message_drawn:
	add	edi,[video_pitch]
	add	edi,[video_pitch]
	mov	cx,1000h
	mov	ah,1
	int	10h
	movzx	eax,[message_width]
	sub	al,[buttons_width]
	and	al,not 1
	add	edi,eax
	cmp	byte [esp+3],2
	jae	two_button_message
	pop	eax
	mov	ah,al
	mov	esi,[first_button]
	call	draw_button
    wait_for_ok:
	call	wait_for_input
	cmp	ah,1
	je	message_aborted
	cmp	al,20h
	je	message_ok
	cmp	al,0Dh
	jne	wait_for_ok
    message_ok:
	mov	eax,1
	ret
    message_aborted:
	xor	eax,eax
	ret
    two_button_message:
	pop	edx
	xor	cl,cl
	test	edx,10000h
	jnz	two_button_loop
	mov	cl,-1
    two_button_loop:
	push	edi
	mov	al,dl
	and	al,cl
	mov	ah,cl
	not	ah
	and	ah,dh
	or	ah,al
	mov	esi,[first_button]
	call	draw_button
	add	edi,2*2
	mov	al,dh
	and	al,cl
	mov	ah,cl
	not	ah
	and	ah,dl
	or	ah,al
	mov	esi,[second_button]
	call	draw_button
	push	ecx edx
	call	wait_for_input
	pop	edx ecx edi
	cmp	ah,1
	je	message_aborted
	cmp	al,9
	je	two_button_switch
	cmp	ah,0Fh
	je	two_button_switch
	cmp	ah,4Bh
	je	two_button_switch
	cmp	ah,4Dh
	je	two_button_switch
	cmp	ah,48h
	je	two_button_switch
	cmp	ah,50h
	je	two_button_switch
	cmp	al,0Dh
	je	button_selected
	cmp	al,20h
	je	button_selected
	mov	ebx,lower_case_table
	xlatb
	mov	ah,al
	mov	esi,[first_button]
	mov	al,[esi]
	xlatb
	cmp	al,ah
	je	message_ok
	mov	esi,[second_button]
	mov	al,[esi]
	xlatb
	cmp	al,ah
	je	message_second_choice
	jmp	two_button_loop
    button_selected:
	or	cl,cl
	jnz	message_ok
    message_second_choice:
	mov	eax,2
	ret
    two_button_switch:
	not	cl
	jmp	two_button_loop
    draw_button:
	push	es gs
	pop	es
	mov	al,'['
	stosw
	mov	al,20h
	stosw
	stosw
    draw_button_label:
	lodsb
	or	al,al
	jz	button_label_ok
	stosw
	jmp	draw_button_label
    button_label_ok:
	mov	al,20h
	stosw
	stosw
	mov	al,']'
	stosw
	pop	es
	ret
  draw_centered_window:
	mov	dl,byte [screen_width]
	sub	dl,cl
	shr	dl,1
	mov	dh,byte [screen_height]
	sub	dh,ch
	shr	dh,1
	test	[command_flags],80h
	jz	draw_window
	mov	ebx,[caret_line_number]
	sub	ebx,[window_line_number]
	add	ebx,3
	cmp	bl,dh
	jbe	draw_window
	mov	al,dh
	add	al,ch
	add	al,3
	cmp	al,bl
	jb	draw_window
	mov	dh,bl
	movzx	edi,ch
	add	edi,ebx
	add	edi,2
	cmp	edi,[screen_height]
	jb	draw_window
	sub	dh,ch
	sub	dh,4
  draw_window:
	push	es gs
	pop	es
	movzx	edi,dh
	imul	edi,[video_pitch]
	movzx	ebx,dl
	shl	ebx,1
	add	edi,ebx
	movzx	edx,ch
	movzx	ecx,cl
	sub	ecx,4
	sub	edx,2
	push	ecx edi
	mov	al,' '
	stos	word [edi]
	mov	al,'É'
	stos	word [edi]
	mov	al,'Í'
	stos	word [edi]
	dec	ecx
	mov	al,' '
	stos	word [edi]
	dec	ecx
      draw_title:
	lods	byte [esi]
	or	al,al
	jz	title_ok
	stos	word [edi]
	loop	draw_title
	jmp	finish_upper_border
      title_ok:
	mov	al,' '
	stos	word [edi]
	dec	ecx
	jz	finish_upper_border
	mov	al,'Í'
	rep	stos word [edi]
      finish_upper_border:
	mov	al,'»'
	stos	word [edi]
	mov	al,' '
	stos	word [edi]
	pop	edi ecx
	add	edi,[video_pitch]
	lea	ebp,[edi+2*2]
      draw_window_lines:
	push	ecx edi
	mov	al,' '
	stos	word [edi]
	mov	al,'º'
	stos	word [edi]
	mov	al,' '
	rep	stos word [edi]
	mov	al,'º'
	stos	word [edi]
	mov	al,' '
	stos	word [edi]
	mov	byte [es:edi+1],8
	mov	byte [es:edi+3],8
	pop	edi ecx
	add	edi,[video_pitch]
	dec	edx
	jnz	draw_window_lines
	push	ecx edi
	mov	al,' '
	stos	word [edi]
	mov	al,'È'
	stos	word [edi]
	mov	al,'Í'
	rep	stos word [edi]
	mov	al,'¼'
	stos	word [edi]
	mov	al,' '
	stos	word [edi]
	mov	byte [es:edi+1],8
	mov	byte [es:edi+3],8
	pop	edi ecx
	mov	eax,[video_pitch]
	lea	edi,[edi+eax+2*2+1]
	mov	al,8
	add	ecx,4
      finish_bottom_shadow:
	stos	byte [edi]
	inc	edi
	loop	finish_bottom_shadow
	mov	edi,ebp
	mov	eax,edi
	cdq
	idiv	[video_pitch]
	sar	edx,1
	mov	dh,al
	pop	es
	ret
  create_edit_box:
	mov	byte [ebx],1
	mov	[ebx+1],al
	mov	[ebx+2],dx
	mov	[ebx+4],ecx
	xor	eax,eax
	mov	[ebx+8],eax
	mov	[ebx+12],eax
	lea	edi,[ebx+16]
	xor	ecx,ecx
	or	esi,esi
	jz	edit_box_text_ok
      init_edit_box_text:
	lodsb
	or	al,al
	jz	edit_box_text_ok
	stosb
	inc	ecx
	cmp	cx,[ebx+6]
	jb	init_edit_box_text
      edit_box_text_ok:
	mov	[ebx+8],cx
	mov	[ebx+12],cx
	xor	al,al
	stosb
	test	byte [ebx+1],1
	jz	draw_edit_box
    set_edit_box_focus:
	push	ebx
	mov	ah,1
	mov	cx,0D0Eh
	int	10h
	pop	ebx
	jmp	draw_edit_box
    kill_edit_box_focus:
	mov	word [ebx+10],0
	push	ebx
	mov	ah,1
	mov	cx,1000h
	int	10h
	pop	ebx
    draw_edit_box:
	test	byte [ebx+1],1
	jz	edit_box_position_ok
	mov	ax,[ebx+10]
	sub	ax,[ebx+12]
	jae	edit_box_position_correction
	movzx	ax,byte [ebx+4]
	add	ax,[ebx+10]
	sub	ax,2
	sub	ax,[ebx+12]
	jae	edit_box_position_ok
    edit_box_position_correction:
	sub	[ebx+10],ax
    edit_box_position_ok:
	push	es gs
	pop	es
	movzx	edi,byte [ebx+3]
	imul	edi,[video_pitch]
	movzx	eax,byte [ebx+2]
	lea	edi,[edi+eax*2]
	mov	al,20h
	cmp	word [ebx+10],0
	je	edit_box_left_edge_ok
	mov	al,1Bh
      edit_box_left_edge_ok:
	mov	ah,[box_colors]
	stosw
	movzx	eax,word [ebx+10]
	lea	esi,[ebx+16+eax]
	movzx	ebp,byte [ebx+4]
	sub	ebp,2
	mov	edx,[ebx+12]
	cmp	dx,[ebx+14]
	jbe	draw_edit_box_before_selection
	ror	edx,16
      draw_edit_box_before_selection:
	movzx	ecx,dx
	sub	cx,[ebx+10]
	jbe	draw_edit_box_selection
	mov	ah,[box_colors]
	call	draw_edit_box_part
      draw_edit_box_selection:
	mov	ax,dx
	sub	ax,cx
	shr	edx,16
	mov	cx,dx
	sub	cx,ax
	jbe	draw_edit_box_after_selection
	mov	ah,[box_selection_colors]
	test	byte [ebx+1],1
	jnz	edit_box_selection_visible
	mov	ah,[box_colors]
      edit_box_selection_visible:
	call	draw_edit_box_part
      draw_edit_box_after_selection:
	mov	ah,[box_colors]
	mov	cx,[ebx+8]
	sub	cx,dx
	jbe	draw_edit_box_ending
	call	draw_edit_box_part
      draw_edit_box_ending:
	mov	ecx,ebp
	mov	al,20h
	rep	stosw
	movzx	edx,word [ebx+8]
	lea	edx,[ebx+16+edx]
	cmp	esi,edx
	jae	edit_box_right_edge_ok
	mov	al,1Ah
      edit_box_right_edge_ok:
	stosw
	test	byte [ebx+1],1
	jz	edit_box_cursor_ok
	mov	dx,[ebx+2]
	inc	dl
	mov	ax,[ebx+12]
	sub	ax,[ebx+10]
	add	dl,al
	mov	ah,2
	push	ebx
	mov	bh,0
	int	10h
	pop	ebx
      edit_box_cursor_ok:
	pop	es
	ret
      draw_edit_box_part:
	or	bp,bp
	jz	edit_box_part_ok
	cmp	cx,bp
	jbe	edit_box_part_length_ok
	mov	cx,bp
      edit_box_part_length_ok:
	sub	bp,cx
      draw_edit_box_character:
	lodsb
	stosw
	loopw	draw_edit_box_character
      edit_box_part_ok:
	ret
  set_box_focus:
	or	byte [ebx+1],1
	mov	cl,[ebx]
	cmp	cl,1
	jb	set_check_box_focus
	je	set_edit_box_focus
	cmp	cl,2
	je	draw_list_box
	ret
  kill_box_focus:
	and	byte [ebx+1],not 1
	mov	cl,[ebx]
	cmp	cl,1
	je	kill_edit_box_focus
	cmp	cl,2
	je	draw_list_box
	ret
  update_box:
	cmp	byte [ebx],0
	je	update_check_box
	ret
  process_box_command:
	mov	cl,[ebx]
	cmp	cl,1
	jb	check_box_command
	je	edit_box_command
	cmp	cl,2
	je	list_box_command
	stc
	ret
    edit_box_command:
	cmp	al,0E0h
	jne	edit_box_ascii_code
	cmp	ah,4Bh
	je	edit_box_left_key
	cmp	ah,4Dh
	je	edit_box_right_key
	cmp	ah,47h
	je	edit_box_home_key
	cmp	ah,4Fh
	je	edit_box_end_key
	cmp	ah,53h
	je	edit_box_delete
	cmp	ah,52h
	je	edit_box_insert
	cmp	ah,93h
	je	edit_box_ctrl_delete
	cmp	ah,92h
	je	edit_box_ctrl_insert
    edit_box_unknown_command:
	stc
	ret
      edit_box_ascii_code:
	cmp	al,8
	je	edit_box_backspace
	cmp	al,18h
	je	edit_box_cut_block
	cmp	al,3
	je	edit_box_ctrl_insert
	cmp	al,16h
	je	edit_box_paste_block
	cmp	al,20h
	jb	edit_box_unknown_command
	test	byte [ebx+1],100b
	jz	edit_box_ascii_code_ok
	cmp	al,30h
	jb	edit_box_command_done
	cmp	al,39h
	ja	edit_box_command_done
      edit_box_ascii_code_ok:
	mov	dx,word [ebx+12]
	cmp	dx,word [ebx+14]
	je	edit_box_character
	push	eax
	call	edit_box_delete_block
	pop	eax
    edit_box_character:
	call	edit_box_insert_character
	jc	edit_box_command_done
	jmp	edit_box_no_selection
    edit_box_delete:
	test	byte [fs:17h],11b
	jnz	edit_box_cut_block
	mov	dx,word [ebx+12]
	cmp	dx,word [ebx+14]
	jne	edit_box_ctrl_delete
	cmp	dx,[ebx+8]
	je	edit_box_command_done
	inc	dx
	mov	[ebx+14],dx
	jmp	edit_box_ctrl_delete
    edit_box_backspace:
	mov	dx,[ebx+12]
	cmp	dx,word [ebx+14]
	jne	edit_box_ctrl_delete
	or	dx,dx
	jz	edit_box_command_done
	dec	word [ebx+12]
	mov	[ebx+14],dx
    edit_box_ctrl_delete:
	call	edit_box_delete_block
	jmp	edit_box_no_selection
    edit_box_ctrl_insert:
	call	edit_box_copy_block
	jmp	edit_box_command_done
    edit_box_cut_block:
	call	edit_box_copy_block
	call	edit_box_delete_block
	jmp	edit_box_no_selection
    edit_box_insert_character:
	test	byte [ebx+1],100b
	jz	edit_box_character_allowed
	cmp	al,30h
	jb	edit_box_disallowed_character
	cmp	al,39h
	ja	edit_box_disallowed_character
      edit_box_character_allowed:
	movzx	ecx,word [ebx+8]
	cmp	cx,[ebx+6]
	je	edit_box_full
	lea	edi,[ebx+16+ecx]
	lea	esi,[edi-1]
	sub	cx,[ebx+12]
	std
	rep	movsb
	cld
	stosb
	inc	word [ebx+8]
	inc	word [ebx+12]
      edit_box_disallowed_character:
	clc
	ret
      edit_box_full:
	stc
	ret
    edit_box_delete_block:
	movzx	eax,word [ebx+12]
	lea	esi,[ebx+16+eax]
	movzx	eax,word [ebx+14]
	lea	edi,[ebx+16+eax]
	movzx	eax,word [ebx+8]
	lea	ecx,[ebx+16+eax]
	cmp	esi,edi
	jae	edit_box_shift_rest_of_line
	xchg	esi,edi
      edit_box_shift_rest_of_line:
	sub	ecx,esi
	mov	eax,edi
	rep	movsb
	mov	ecx,esi
	sub	ecx,edi
	sub	[ebx+8],cx
	sub	eax,ebx
	sub	eax,16
	mov	[ebx+12],ax
	mov	[ebx+14],ax
	ret
    edit_box_copy_block:
	movzx	ecx,word [ebx+12]
	movzx	edx,word [ebx+14]
	cmp	ecx,edx
	je	edit_box_block_copied
	ja	edit_box_block_start_ok
	xchg	ecx,edx
    edit_box_block_start_ok:
	sub	ecx,edx
	lea	esi,[ebx+16+edx]
	push	ebx esi ecx
	cmp	[clipboard],0
	je	edit_box_allocate_clipboard
	mov	ebx,[clipboard_handle]
	call	release_memory
    edit_box_allocate_clipboard:
	mov	ecx,[esp]
	inc	ecx
	call	get_memory
	mov	[clipboard],eax
	mov	[clipboard_handle],ecx
	or	eax,eax
	jz	not_enough_memory
	mov	edi,eax
	pop	ecx esi ebx
	rep	movsb
	xor	al,al
	stosb
    edit_box_block_copied:
	ret
    edit_box_insert:
	test	byte [fs:17h],11b
	jz	edit_box_command_done
    edit_box_paste_block:
	call	edit_box_delete_block
	mov	esi,[clipboard]
	or	esi,esi
	jz	edit_box_command_done
      edit_box_insert_block:
	lodsb
	or	al,al
	jz	edit_box_no_selection
	cmp	al,0Dh
	je	edit_box_no_selection
	push	esi
	call	edit_box_insert_character
	pop	esi
	jnc	edit_box_insert_block
	jmp	edit_box_no_selection
    edit_box_left_key:
	cmp	word [ebx+12],0
	je	edit_box_no_selection
	dec	word [ebx+12]
	jmp	edit_box_moved_cursor
    edit_box_right_key:
	mov	ax,[ebx+8]
	cmp	[ebx+12],ax
	je	edit_box_no_selection
	inc	word [ebx+12]
	jmp	edit_box_moved_cursor
    edit_box_home_key:
	mov	word [ebx+12],0
	jmp	edit_box_moved_cursor
    edit_box_end_key:
	mov	ax,[ebx+8]
	mov	[ebx+12],ax
	jmp	edit_box_moved_cursor
    edit_box_moved_cursor:
	test	byte [fs:17h],11b
	jnz	edit_box_redraw
    edit_box_no_selection:
	mov	ax,[ebx+12]
	mov	[ebx+14],ax
    edit_box_redraw:
	call	draw_edit_box
    edit_box_command_done:
	movzx	eax,word [ebx+8]
	mov	byte [ebx+16+eax],0
	clc
	ret
  create_list_box:
	mov	byte [ebx],2
	mov	[ebx+1],al
	mov	[ebx+2],dx
	mov	[ebx+4],ecx
	xor	eax,eax
	mov	[ebx+8],eax
	mov	[ebx+12],esi
    draw_list_box:
	mov	ax,[ebx+8]
	sub	ax,[ebx+10]
	jb	list_box_adjust_up
	movzx	dx,byte [ebx+5]
	sub	ax,dx
	jb	list_box_adjustments_ok
	inc	ax
	add	[ebx+10],ax
	jmp	list_box_adjustments_ok
      list_box_adjust_up:
	add	[ebx+10],ax
      list_box_adjustments_ok:
	movzx	edi,byte [ebx+3]
	imul	edi,[video_pitch]
	movzx	ecx,byte [ebx+2]
	lea	edi,[edi+ecx*2]
	movzx	edx,word [ebx+10]
	push	es gs
	pop	es
    draw_list_box_row:
	mov	ah,[box_colors]
	movzx	ecx,byte [ebx+4]
	cmp	dx,[ebx+6]
	jae	draw_empty_list_box_row
	mov	esi,[ebx+12]
	mov	esi,[esi+edx*4]
	test	byte [ebx+1],1
	jz	list_box_row_colors_ok
	cmp	dx,[ebx+8]
	jne	list_box_row_colors_ok
	mov	ah,[box_selection_colors]
      list_box_row_colors_ok:
	sub	ecx,2
	mov	al,20h
	stosw
      draw_list_box_item:
	lodsb
	test	al,al
	jnz	draw_list_box_item_character
	dec	esi
	mov	al,20h
      draw_list_box_item_character:
	stosw
	loop	draw_list_box_item
	mov	al,20h
	cmp	byte [esi],0
	je	list_box_item_ending
	mov	al,1Ah
      list_box_item_ending:
	stosw
	jmp	list_box_row_drawn
    draw_empty_list_box_row:
	mov	al,20h
	rep	stosw
    list_box_row_drawn:
	inc	edx
	mov	ax,dx
	sub	ax,[ebx+10]
	cmp	al,[ebx+5]
	jae	list_box_drawn
	add	edi,[video_pitch]
	movzx	ecx,byte [ebx+4]
	shl	ecx,1
	sub	edi,ecx
	jmp	draw_list_box_row
    list_box_drawn:
	pop	es
	ret
    list_box_command:
	cmp	ah,48h
	je	list_box_up_key
	cmp	ah,50h
	je	list_box_down_key
	cmp	ah,47h
	je	list_box_home_key
	cmp	ah,4Fh
	je	list_box_end_key
	cmp	ah,49h
	je	list_box_pgup_key
	cmp	ah,51h
	je	list_box_pgdn_key
	stc
	ret
    list_box_home_key:
	xor	eax,eax
	mov	[ebx+8],ax
	jmp	list_box_redraw
    list_box_end_key:
	mov	ax,[ebx+6]
	dec	ax
	mov	[ebx+8],ax
	jmp	list_box_redraw
    list_box_pgup_key:
	movzx	ax,byte [ebx+5]
	sub	[ebx+8],ax
	jae	list_box_redraw
	mov	word [ebx+8],0
	jmp	list_box_redraw
    list_box_pgdn_key:
	movzx	ax,byte [ebx+5]
	add	[ebx+8],ax
	mov	ax,[ebx+6]
	dec	ax
	cmp	[ebx+8],ax
	jbe	list_box_redraw
	mov	[ebx+8],ax
	jmp	list_box_redraw
    list_box_up_key:
	mov	ax,[ebx+8]
	sub	ax,1
	jc	list_box_command_done
	dec	word [ebx+8]
	jmp	list_box_redraw
    list_box_down_key:
	mov	ax,[ebx+8]
	inc	ax
	cmp	ax,[ebx+6]
	jae	list_box_command_done
	mov	[ebx+8],ax
    list_box_redraw:
	call	draw_list_box
    list_box_command_done:
	clc
	ret
  create_check_box:
	mov	byte [ebx],0
	mov	[ebx+1],al
	mov	[ebx+2],dx
	mov	[ebx+4],cl
	mov	[ebx+8],ebp
	mov	[ebx+12],edi
	movzx	edx,byte [ebx+3]
	imul	edx,[video_pitch]
	movzx	ecx,byte [ebx+2]
	lea	edx,[edx+ecx*2]
	mov	al,'['
	test	byte [ebx+1],2
	jz	draw_check_box_left_bracket
	mov	al,'('
      draw_check_box_left_bracket:
	mov	byte [gs:edx],al
	add	edx,2
	mov	al,20h
	test	byte [ebx+1],2
	jnz	set_up_radio_initial_state
	test	[edi],ebp
	jz	draw_check_box_initial_state
	mov	al,'+'
	jmp	draw_check_box_initial_state
      set_up_radio_initial_state:
	cmp	[edi],ebp
	jne	draw_check_box_initial_state
	mov	al,7
      draw_check_box_initial_state:
	mov	byte [gs:edx],al
	add	edx,2
	mov	al,']'
	test	byte [ebx+1],2
	jz	draw_check_box_right_bracket
	mov	al,')'
      draw_check_box_right_bracket:
	mov	byte [gs:edx],al
	add	edx,2*2
	movzx	ecx,byte [ebx+4]
      draw_check_box_text:
	lodsb
	or	al,al
	jz	check_box_text_ok
	mov	[gs:edx],al
	add	edx,2
	loop	draw_check_box_text
      check_box_text_ok:
	test	byte [ebx+1],1
	jnz	set_check_box_focus
	ret
    set_check_box_focus:
	push	ebx
	mov	ah,2
	mov	dx,[ebx+2]
	inc	dl
	xor	bh,bh
	int	10h
	mov	ah,1
	mov	cx,0D0Eh
	int	10h
	pop	ebx
	ret
    check_box_command:
	cmp	al,20h
	je	switch_check_box_state
	stc
	ret
    switch_check_box_state:
	mov	edi,[ebx+12]
	mov	eax,[ebx+8]
	test	byte [ebx+1],2
	jnz	set_radio_state
	xor	[edi],eax
	call	update_check_box
	clc
	ret
      set_radio_state:
	mov	[edi],eax
	call	update_check_box
	clc
	ret
    update_check_box:
	movzx	edx,byte [ebx+3]
	imul	edx,[video_pitch]
	movzx	ecx,byte [ebx+2]
	lea	edx,[edx+(ecx+1)*2]
	mov	edi,[ebx+12]
	mov	eax,[ebx+8]
	test	byte [ebx+1],2
	jnz	redraw_radio
	test	[edi],eax
	mov	al,20h
	jz	check_box_state_ok
	mov	al,'+'
      check_box_state_ok:
	mov	byte [gs:edx],al
	ret
      redraw_radio:
	cmp	[edi],eax
	mov	al,20h
	jne	radio_state_ok
	mov	al,7
      radio_state_ok:
	mov	byte [gs:edx],al
	ret

  init_common_dialog:
	xor	eax,eax
	mov	[boxes_count],eax
	mov	[current_box],eax
	ret
  register_box_in_dialog:
	mov	eax,[boxes_count]
	inc	[boxes_count]
	mov	[boxes+eax*4],ebx
	test	byte [ebx+1],1
	jz	box_registered
	mov	[current_box],eax
      box_registered:
	ret
  common_dialog_loop:
	call	wait_for_input
	cmp	ah,1
	je	common_dialog_aborted
	cmp	al,0Dh
	je	common_dialog_ok
	cmp	al,9
	je	common_dialog_cycle_boxes
	cmp	ah,0Fh
	je	common_dialog_reverse_cycle_boxes
	mov	edx,[current_box]
	mov	ebx,[boxes+edx*4]
	call	process_box_command
	jnc	common_dialog_command_processed
	cmp	ah,48h
	je	common_dialog_previous_box
	cmp	ah,50h
	je	common_dialog_next_box
	cmp	ah,4Bh
	je	common_dialog_previous_box
	cmp	ah,4Dh
	je	common_dialog_next_box
	jmp	common_dialog_loop
      common_dialog_command_processed:
	xor	edx,edx
      update_boxes:
	mov	ebx,[boxes+edx*4]
	push	edx
	call	update_box
	pop	edx
	inc	edx
	cmp	edx,[boxes_count]
	jb	update_boxes
	mov	eax,[common_dialog_callback]
	test	eax,eax
	jz	common_dialog_loop
	call	eax
	jmp	common_dialog_loop
      common_dialog_next_box:
	mov	edx,[current_box]
	lea	eax,[edx+1]
	cmp	eax,[boxes_count]
	je	common_dialog_loop
	mov	[current_box],eax
	jmp	common_dialog_switch_box
      common_dialog_previous_box:
	mov	edx,[current_box]
	or	edx,edx
	jz	common_dialog_loop
	dec	[current_box]
	jmp	common_dialog_switch_box
      common_dialog_cycle_boxes:
	mov	edx,[current_box]
	inc	[current_box]
	mov	eax,[current_box]
	cmp	eax,[boxes_count]
	jb	common_dialog_switch_box
	mov	[current_box],0
	jmp	common_dialog_switch_box
      common_dialog_reverse_cycle_boxes:
	mov	edx,[current_box]
	sub	[current_box],1
	jnc	common_dialog_switch_box
	mov	eax,[boxes_count]
	add	[current_box],eax
      common_dialog_switch_box:
	mov	ebx,[boxes+edx*4]
	call	kill_box_focus
	mov	edx,[current_box]
	mov	ebx,[boxes+edx*4]
	call	set_box_focus
	jmp	common_dialog_loop
      common_dialog_ok:
	clc
	ret
      common_dialog_aborted:
	stc
	ret
  get_entered_number:
	xor	edx,edx
      get_digit:
	lodsb
	or	al,al
	jz	entered_number_ok
	sub	al,30h
	movzx	eax,al
	imul	edx,10
	add	edx,eax
	jmp	get_digit
      entered_number_ok:
	ret
  draw_static:
	lodsb
	or	al,al
	jz	fill_static
	mov	[gs:edi],al
	add	edi,2
	loop	draw_static
	ret
      fill_static:
	mov	byte [gs:edi],20h
	add	edi,2
	loop	fill_static
	dec	esi
	ret

  file_open_dialog:
	push	esi
	mov	edi,buffer+3000h
	mov	byte [edi],0
	call	get_current_directory
	cmp	byte [edi-2],'\'
	je	browser_startup_path_ok
	mov	word [edi-1],'\'
      browser_startup_path_ok:
	xor	eax,eax
	mov	[file_list_buffer_handle],eax
	call	make_list_of_files
	pop	esi
	mov	dx,0308h
	mov	cl,35h
	mov	ch,byte [screen_height]
	sub	ch,7
	mov	ah,[window_colors]
	call	draw_window
	push	edx
	mov	eax,[video_pitch]
	mov	edx,[screen_height]
	sub	edx,11
	imul	edx,eax
	lea	edx,[edi+edx+8*2]
	mov	[current_box],edx
	lea	edi,[edi+eax+2*2]
	mov	esi,_file
	mov	ecx,5
	call	draw_static
	mov	ebx,filename_buffer
	xor	esi,esi
	mov	ecx,27h + 256 shl 16
	mov	edx,[esp]
	add	dx,0108h
	mov	al,1
	call	create_edit_box
	mov	ebx,boxes
	mov	esi,[file_list]
	mov	ecx,[file_list_buffer_top]
	sub	ecx,esi
	shl	ecx,16-2
	mov	cl,27h
	mov	ch,byte [screen_height]
	sub	ch,15
	pop	edx
	add	dx,0308h
	xor	al,al
	call	create_list_box
	call	draw_browser_path
      file_input_loop:
	call	wait_for_input
	cmp	ah,1
	je	filename_aborted
	cmp	al,0Dh
	je	filename_accepted
	cmp	ah,0Fh
	je	activate_file_browser
	cmp	ah,50h
	je	activate_file_browser
	mov	ebx,filename_buffer
	call	process_box_command
	jmp	file_input_loop
    activate_file_browser:
	mov	ebx,filename_buffer
	call	kill_box_focus
	mov	ebx,boxes
	call	set_box_focus
	call	update_file_input
      file_browser_loop:
	call	wait_for_input
	cmp	ah,1
	je	filename_aborted
	cmp	al,0Dh
	je	filename_accepted
	cmp	ah,0Fh
	je	activate_file_input
	cmp	ah,4Bh
	je	activate_file_input
	cmp	al,8
	je	go_to_parent_directory
	mov	ebx,boxes
	push	dword [ebx+8]
	call	process_box_command
	pop	eax
	cmp	ax,[ebx+8]
	je	file_browser_loop
	call	update_file_input
	jmp	file_browser_loop
      go_to_parent_directory:
	cmp	byte [buffer+3000h+3],0
	je	file_browser_loop
	mov	edi,buffer
	mov	eax,'..'
	stosd
	jmp	browser_chdir
    filename_accepted:
	mov	edx,filename_buffer+16
	movzx	eax,word [edx-16+8]
	test	eax,eax
	jz	got_filename
	cmp	byte [edx+eax-1],'\'
	je	browser_path_entered
	cmp	byte [edx+eax-1],':'
	jne	got_filename
      browser_path_entered:
	mov	esi,edx
	mov	edi,buffer
      copy_path_to_browse:
	lodsb
	stosb
	test	al,al
	jnz	copy_path_to_browse
	cmp	word [buffer+1],':'
	je	browser_directory_ok
	cmp	byte [edi-2],'\'
	jne	browser_chdir
	mov	byte [edi-2],0
      browser_chdir:
	xor	dx,dx
	mov	ax,713Bh
	call	dos_int
	jnc	browser_directory_ok
	cmp	ax,7100h
	jne	file_list_selection_ok
	mov	ah,3Bh
	call	dos_int
	jc	file_list_selection_ok
      browser_directory_ok:
	cmp	byte [buffer+1],':'
	jne	browser_drive_ok
	mov	dl,[buffer]
	sub	dl,'A'
	cmp	dl,'Z'-'A'
	jbe	browser_change_drive
	sub	dl,'a'-'A'
      browser_change_drive:
	mov	ah,0Eh
	int	21h
      browser_drive_ok:
	push	0
	cmp	dword [buffer],'..'
	jne	name_to_select_ok
	mov	edi,buffer+3000h
	mov	al,'\'
      find_last_directory_name:
	mov	esi,edi
	repne	scasb
	cmp	byte [edi],0
	jne	find_last_directory_name
	lea	ecx,[edi-1]
	sub	ecx,esi
	mov	edi,buffer+400h
	mov	[esp],ecx
	mov	ebx,upper_case_table
      get_name_to_select:
	lodsb
	xlatb
	stosb
	loop	get_name_to_select
      name_to_select_ok:
	mov	edi,buffer+3000h
	call	get_current_directory
	jc	browser_drive_invalid
	cmp	byte [edi-2],'\'
	je	browser_new_path_ok
	mov	word [edi-1],'\'
      browser_new_path_ok:
	call	make_list_of_files
	call	draw_browser_path
	mov	ebx,filename_buffer
	xor	eax,eax
	mov	[ebx+8],eax
	mov	[ebx+12],eax
	mov	[ebx+16],al
	mov	ebx,boxes
	mov	esi,[file_list]
	mov	[ebx+12],esi
	mov	ecx,[file_list_buffer_top]
	sub	ecx,esi
	shr	ecx,2
	mov	[ebx+6],cx
	xor	eax,eax
	mov	[ebx+8],eax
	mov	eax,esi
	pop	edx
      find_name_to_select:
	cmp	eax,[file_list_buffer_top]
	je	file_list_selection_ok
	mov	esi,[eax]
	add	esi,2
	mov	edi,buffer+400h
	mov	ecx,edx
	repe	cmpsb
	je	select_directory
	add	eax,4
	jmp	find_name_to_select
      select_directory:
	sub	eax,[file_list]
	shr	eax,2
	mov	[ebx+8],ax
      file_list_selection_ok:
	test	byte [filename_buffer+1],1
	jnz	activate_file_input
	jmp	activate_file_browser
      browser_drive_invalid:
	mov	dl,[buffer+3000h]
	sub	dl,'A'
	cmp	dl,'Z'-'A'
	jbe	browser_restore_drive
	sub	dl,'a'-'A'
      browser_restore_drive:
	mov	ah,0Eh
	int	21h
	pop	eax
	jmp	file_list_selection_ok
    got_filename:
	cmp	[filename_buffer+16],0
	je	file_input_loop
	call	release_list_of_files
	mov	edx,filename_buffer+16
	movzx	ecx,word [filename_buffer+8]
	clc
	ret
    filename_aborted:
	call	release_list_of_files
	stc
	ret
    activate_file_input:
	mov	ebx,boxes
	call	kill_box_focus
	mov	ebx,filename_buffer
	call	set_box_focus
	jmp	file_input_loop
    update_file_input:
	mov	ebx,boxes
	mov	esi,[ebx+12]
	movzx	eax,word [ebx+8]
	mov	esi,[esi+eax*4]
	mov	ah,[esi]
	add	esi,2
	mov	edi,filename_buffer+16
      copy_file_item:
	lodsb
	stosb
	test	al,al
	jnz	copy_file_item
	cmp	ah,[browser_symbols+2]
	je	file_item_copied
	cmp	ah,[browser_symbols+3]
	je	file_item_copied
	mov	byte [edi-1],'\'
	stosb
      file_item_copied:
	mov	ecx,edi
	sub	ecx,1+filename_buffer+16
	mov	ebx,filename_buffer
	mov	[ebx+8],cx
	mov	[ebx+12],cx
	xor	eax,eax
	mov	[ebx+10],ax
	mov	[ebx+14],ax
	call	draw_edit_box
	ret
    draw_browser_path:
	mov	edi,[current_box]
	mov	esi,buffer+3000h
	mov	ecx,27h
	call	draw_static
	add	edi,[video_pitch]
	sub	edi,27h*2
	mov	ecx,27h
	call	draw_static
	ret
    make_list_of_files:
	cmp	[file_list_buffer_handle],0
	je	default_buffer_for_file_list
	mov	edi,[file_list_buffer_top]
	mov	ecx,[file_list_buffer_size]
	sub	edi,ecx
	jmp	init_file_list
      default_buffer_for_file_list:
	mov	edi,buffer+1000h
	mov	ecx,2000h
      init_file_list:
	lea	ebx,[edi+ecx]
	mov	[file_list_buffer_top],ebx
	mov	ah,1Ah
	xor	edx,edx
	call	dos_int
	mov	ah,19h
	int	21h
	mov	dl,al
	mov	ah,0Eh
	int	21h
	movzx	ecx,al
	mov	dword [buffer],'A:'
      list_drives:
	push	ecx edi
	mov	ax,290Ch
	xor	esi,esi
	mov	di,10h
	call	dos_int
	pop	edi
	inc	al
	jz	try_next_drive
	cmp	byte [buffer],'B'
	jne	add_drive
	test	byte [fs:10h],11000000b
	jz	try_next_drive
      add_drive:
	sub	ebx,4
	mov	[ebx],edi
	mov	esi,buffer
	mov	ax,2004h
	stosw
	movsw
	movsb
     try_next_drive:
	inc	byte [buffer]
	pop	ecx
	loop	list_drives
	mov	[file_list],ebx
	mov	[file_list_buffer],edi
	cmp	byte [buffer+3000h],0
	je	file_list_made
	mov	edi,buffer
	mov	eax,'*.*'
	stosd
	mov	ax,714Eh
	mov	cx,31h
	xor	esi,esi
	xor	edx,edx
	mov	di,10h
	call	dos_int
	mov	ebx,eax
	jnc	long_file_names_list
	mov	ah,4Eh
	mov	cx,31h
	xor	edx,edx
	call	dos_int
	jc	file_list_made
      short_file_names_list:
	sub	[file_list],4
	mov	edx,[file_list]
	mov	edi,[file_list_buffer]
	cmp	edi,edx
	jae	not_enough_memory_for_list
	mov	[edx],edi
	mov	esi,buffer+1Eh
	test	byte [esi-1Eh+15h],10h
	jnz	short_directory_name
	mov	ebx,lower_case_table
	mov	ax,2003h
	stosw
	jmp	copy_short_file_name
      short_directory_name:
	mov	ebx,upper_case_table
	cmp	word [esi],'..'
	je	short_parent_directory
	cmp	byte [esi],'.'
	je	short_directory_to_hide
	mov	ax,2002h
	stosw
	jmp	copy_short_file_name
      short_parent_directory:
	cmp	byte [buffer+3000h+3],0
	je	short_directory_to_hide
	mov	ax,2001h
	stosw
      copy_short_file_name:
	lodsb
	xlat	byte [ebx]
	cmp	edi,[file_list]
	jae	not_enough_memory_for_list
	stosb
	test	al,al
	jnz	copy_short_file_name
      short_file_name_copied:
	mov	[file_list_buffer],edi
	mov	ah,4Fh
	call	dos_int
	jnc	short_file_names_list
	jmp	file_list_made
      short_directory_to_hide:
	add	[file_list],4
	jmp	short_file_name_copied
      not_enough_memory_for_long_file_name:
	pop	ebx
	mov	ax,71A1h
	call	dos_int
      not_enough_memory_for_list:
	cmp	[file_list_buffer_handle],0
	jne	really_not_enough_memory_for_list
	mov	ax,500h
	mov	edi,buffer
	int	31h
	mov	ecx,[edi]
	cmp	ecx,2000h
	jbe	really_not_enough_memory_for_list
	cmp	ecx,100000h
	jbe	allocate_buffer_for_file_list
	mov	ecx,100000h
      allocate_buffer_for_file_list:
	mov	[file_list_buffer_size],ecx
	call	get_memory
	or	eax,eax
	jz	really_not_enough_memory_for_list
	mov	[file_list_buffer_handle],ebx
	mov	edi,eax
	mov	ecx,[file_list_buffer_size]
	jmp	init_file_list
      really_not_enough_memory_for_list:
	add	[file_list],4
	jmp	file_list_made
      long_file_names_list:
	push	ebx
	sub	[file_list],4
	mov	edx,[file_list]
	mov	edi,[file_list_buffer]
	cmp	edi,edx
	jae	not_enough_memory_for_long_file_name
	mov	[edx],edi
	mov	esi,buffer+10h+2Ch
	test	byte [esi-2Ch],10h
	jnz	long_directory_name
	mov	ax,2003h
	stosw
	mov	ebx,lower_case_table
	jmp	copy_long_file_name
      long_directory_to_hide:
	add	[file_list],4
	jmp	long_file_name_copied
      long_directory_name:
	mov	ebx,upper_case_table
	cmp	byte [esi],'.'
	jne	long_directory_show
	cmp	byte [esi+1],0
	je	long_directory_to_hide
	cmp	word [esi+1],'.'
	jne	long_directory_show
	cmp	byte [buffer+3000h+3],0
	je	long_directory_to_hide
	mov	ax,2001h
	stosw
	jmp	copy_long_file_name
      long_directory_show:
	mov	ax,2002h
	stosw
      copy_long_file_name:
	lodsb
	xlatb
	cmp	edi,[file_list]
	jae	not_enough_memory_for_long_file_name
	stosb
	test	al,al
	jnz	copy_long_file_name
      long_file_name_copied:
	mov	[file_list_buffer],edi
	pop	ebx
	mov	ax,714Fh
	xor	esi,esi
	mov	di,10h
	call	dos_int
	jnc	long_file_names_list
	mov	ax,71A1h
	call	dos_int
      file_list_made:
	mov	edx,[file_list_buffer_top]
	sub	edx,[file_list]
	shr	edx,2
	mov	ebp,edx
      sort_file_list:
	shr	ebp,1
	jz	file_list_sorted
	mov	ebx,ebp
      sorting_iteration:
	cmp	ebx,edx
	jae	sort_file_list
	mov	eax,ebx
      place_into_right_blocks:
	cmp	eax,ebp
	jb	sort_next_offset
	push	edx
	mov	edx,eax
	sub	eax,ebp
	push	eax
	mov	esi,[file_list]
	lea	eax,[esi+eax*4]
	lea	edx,[esi+edx*4]
	mov	esi,[eax]
	mov	edi,[edx]
	mov	ecx,257
	repe	cmpsb
	jbe	exchange_ok
	mov	esi,[eax]
	xchg	esi,[edx]
	mov	[eax],esi
      exchange_ok:
	pop	eax edx
	jmp	place_into_right_blocks
      sort_next_offset:
	inc	ebx
	jmp	sorting_iteration
      file_list_sorted:
	mov	esi,[file_list]
	mov	ebx,browser_symbols
      make_browser_symbols:
	cmp	esi,[file_list_buffer_top]
	je	file_list_done
	mov	edx,[esi]
	mov	al,[edx]
	dec	al
	xlatb
	mov	[edx],al
	add	esi,4
	jmp	make_browser_symbols
      file_list_done:
	ret
    release_list_of_files:
	mov	ebx,[file_list_buffer_handle]
	test	ebx,ebx
	jz	list_of_files_released
	call	release_memory
      list_of_files_released:
	ret
  goto_dialog:
	mov	esi,_position
	mov	dx,080Bh
	mov	cx,0719h
	mov	ah,[window_colors]
	call	draw_window
	push	edx
	push	edi
	mov	eax,[video_pitch]
	lea	edi,[edi+eax+5*2]
	mov	esi,_row
	mov	ecx,4
	call	draw_static
	pop	edi
	mov	eax,[video_pitch]
	lea	eax,[eax*3]
	lea	edi,[edi+eax+2*2]
	mov	esi,_column
	mov	ecx,7
	call	draw_static
	call	init_common_dialog
	mov	edi,buffer+200h
	mov	esi,edi
	mov	eax,[caret_line_number]
	call	number_as_text
	xor	al,al
	stosb
	mov	dx,[esp]
	mov	ebx,buffer
	mov	ecx,9 + 7 shl 16
	add	dx,010Ah
	mov	al,101b
	call	create_edit_box
	call	register_box_in_dialog
	mov	edi,buffer+200h
	mov	esi,edi
	mov	eax,[caret_position]
	inc	eax
	call	number_as_text
	xor	al,al
	stosb
	pop	edx
	mov	ebx,buffer+100h
	mov	ecx,9 + 7 shl 16
	add	dx,030Ah
	mov	al,100b
	call	create_edit_box
	call	register_box_in_dialog
	mov	[common_dialog_callback],0
	call	common_dialog_loop
	jc	goto_dialog_done
	mov	esi,buffer+16
	call	get_entered_number
	mov	ecx,edx
	mov	esi,buffer+100h+16
	call	get_entered_number
	clc
      goto_dialog_done:
	ret
  find_dialog:
	push	[find_flags]
	mov	esi,_find
	mov	dx,060Dh
	mov	cx,0936h
	mov	ah,[window_colors]
	call	draw_window
	push	edx
	mov	eax,[video_pitch]
	lea	edi,[edi+eax+2*2]
	mov	esi,_text_to_find
	mov	ecx,13
	call	draw_static
	call	init_common_dialog
	call	get_word_at_caret
	mov	edi,[line_buffer]
	mov	esi,[caret_line]
	call	copy_from_line
	xor	al,al
	stosb
	mov	dx,[esp]
	mov	ebx,buffer
	mov	esi,[line_buffer]
	mov	ecx,32 + 1000 shl 16
	add	dx,0110h
	mov	al,1
	call	create_edit_box
	call	register_box_in_dialog
	mov	dx,[esp]
	mov	ebx,buffer+800h
	mov	esi,_case_sensitive
	mov	edi,find_flags
	mov	ebp,AEFIND_CASESENSITIVE
	add	dx,0310h
	mov	cl,10h
	xor	al,al
	call	create_check_box
	call	register_box_in_dialog
	mov	dx,[esp]
	mov	ebx,buffer+810h
	mov	esi,_whole_words
	mov	edi,find_flags
	mov	ebp,AEFIND_WHOLEWORDS
	add	dx,0410h
	mov	cl,10h
	xor	al,al
	call	create_check_box
	call	register_box_in_dialog
	pop	edx
	mov	ebx,buffer+820h
	mov	esi,_backward
	mov	edi,find_flags
	mov	ebp,AEFIND_BACKWARD
	add	dx,0510h
	mov	cl,10h
	xor	al,al
	call	create_check_box
	call	register_box_in_dialog
	mov	[common_dialog_callback],0
	call	common_dialog_loop
	pop	eax
	jc	find_dialog_aborted
	mov	esi,buffer+16
	mov	eax,[find_flags]
	clc
	ret
      find_dialog_aborted:
	mov	[find_flags],eax
	ret
  replace_dialog:
	push	[find_flags]
	mov	esi,_replace
	mov	dx,060Dh
	mov	cx,0C36h
	mov	ah,[window_colors]
	call	draw_window
	push	edx
	push	edi
	mov	eax,[video_pitch]
	lea	edi,[edi+eax+2*2]
	mov	esi,_text_to_find
	mov	ecx,13
	call	draw_static
	pop	edi
	mov	eax,[video_pitch]
	imul	eax,3
	lea	edi,[edi+eax+6*2]
	mov	esi,_new_text
	mov	ecx,9
	call	draw_static
	call	init_common_dialog
	call	get_word_at_caret
	mov	edi,[line_buffer]
	mov	esi,[caret_line]
	call	copy_from_line
	xor	al,al
	stosb
	mov	dx,[esp]
	mov	ebx,buffer
	mov	esi,[line_buffer]
	mov	ecx,32 + 1000 shl 16
	add	dx,0110h
	mov	al,1
	call	create_edit_box
	call	register_box_in_dialog
	mov	dx,[esp]
	mov	ebx,buffer+400h
	xor	esi,esi
	mov	ecx,32 + 1000 shl 16
	add	dx,0310h
	xor	al,al
	call	create_edit_box
	call	register_box_in_dialog
	mov	dx,[esp]
	mov	ebx,buffer+800h
	mov	esi,_case_sensitive
	mov	edi,find_flags
	mov	ebp,AEFIND_CASESENSITIVE
	add	dx,0510h
	mov	cl,18h
	xor	al,al
	call	create_check_box
	call	register_box_in_dialog
	mov	dx,[esp]
	mov	ebx,buffer+810h
	mov	esi,_whole_words
	mov	edi,find_flags
	mov	ebp,AEFIND_WHOLEWORDS
	add	dx,0610h
	mov	cl,18h
	xor	al,al
	call	create_check_box
	call	register_box_in_dialog
	mov	dx,[esp]
	mov	ebx,buffer+820h
	mov	esi,_backward
	mov	edi,find_flags
	mov	ebp,AEFIND_BACKWARD
	add	dx,0710h
	mov	cl,18h
	xor	al,al
	call	create_check_box
	call	register_box_in_dialog
	pop	edx
	mov	ebx,buffer+830h
	mov	esi,_prompt
	mov	edi,command_flags
	mov	ebp,1
	add	dx,0810h
	mov	cl,18h
	xor	al,al
	call	create_check_box
	call	register_box_in_dialog
	mov	[common_dialog_callback],0
	call	common_dialog_loop
	pop	eax
	jc	replace_dialog_aborted
	mov	esi,buffer+16
	mov	edi,buffer+400h+16
	mov	eax,[find_flags]
	clc
	ret
      replace_dialog_aborted:
	mov	[find_flags],eax
	ret
  options_dialog:
	mov	esi,_options
	mov	dx,0616h
	mov	cx,0922h
	mov	ah,[window_colors]
	call	draw_window
	push	edx
	call	init_common_dialog
	mov	ebx,buffer
	mov	esi,_secure_selection
	mov	edi,editor_style
	mov	ebp,AES_SECURESEL
	add	dx,0102h
	mov	cl,16h
	mov	al,1
	call	create_check_box
	call	register_box_in_dialog
	mov	dx,[esp]
	mov	ebx,buffer+10h
	mov	esi,_auto_brackets
	mov	edi,editor_style
	mov	ebp,AES_AUTOBRACKETS
	add	dx,0202h
	mov	cl,16h
	xor	al,al
	call	create_check_box
	call	register_box_in_dialog
	mov	dx,[esp]
	mov	ebx,buffer+20h
	mov	esi,_auto_indent
	mov	edi,editor_style
	mov	ebp,AES_AUTOINDENT
	add	dx,0302h
	mov	cl,16h
	xor	al,al
	call	create_check_box
	call	register_box_in_dialog
	mov	dx,[esp]
	mov	ebx,buffer+30h
	mov	esi,_smart_tabs
	mov	edi,editor_style
	mov	ebp,AES_SMARTTABS
	add	dx,0402h
	mov	cl,16h
	xor	al,al
	call	create_check_box
	call	register_box_in_dialog
	pop	edx
	mov	ebx,buffer+40h
	mov	esi,_optimal_fill
	mov	edi,editor_style
	mov	ebp,AES_OPTIMALFILL
	add	dx,0502h
	mov	cl,16h
	xor	al,al
	call	create_check_box
	call	register_box_in_dialog
	mov	[common_dialog_callback],0
	jmp	common_dialog_loop
  ascii_table_window:
	mov	esi,_ascii_table
	mov	dx,0616h
	mov	cx,0C24h
	mov	ah,[window_colors]
	call	draw_window
	push	edx
	mov	ah,[window_colors]
	xor	al,al
	mov	edx,8
      draw_ascii_table:
	mov	ecx,32
      draw_ascii_row:
	mov	[gs:edi],ax
	add	edi,2
	inc	al
	loop	draw_ascii_row
	add	edi,[video_pitch]
	sub	edi,32*2
	dec	edx
	jnz	draw_ascii_table
	mov	ecx,32
      draw_ascii_table_border:
	mov	byte [gs:edi+(ecx-1)*2],'Ä'
	loop	draw_ascii_table_border
	add	edi,[video_pitch]
	push	edi
	mov	ah,1
	mov	cx,000Fh
	int	10h
      ascii_table_update:
	mov	dl,[selected_character]
	mov	dh,dl
	and	dl,11111b
	shr	dh,5
	add	dx,word [esp+4]
	mov	ah,2
	xor	bh,bh
	int	10h
	mov	edi,screen_row_buffer+10h
	mov	eax,'Dec:'
	stosd
	mov	al,20h
	stosb
	movzx	eax,[selected_character]
	call	number_as_text
	mov	al,20h
	stosb
	mov	eax,'Hex:'
	stosd
	mov	al,20h
	stosb
	mov	al,[selected_character]
	shr	al,4
	cmp	al,10
	sbb	al,69h
	das
	stosb
	mov	al,[selected_character]
	and	al,0Fh
	cmp	al,10
	sbb	al,69h
	das
	stosb
	xor	al,al
	stosb
	sub	edi,30+1
	mov	esi,edi
	mov	eax,'Char'
	stosd
	mov	eax,'acte'
	stosd
	mov	eax,'r:  '
	stosd
	mov	ecx,screen_row_buffer+10h
	sub	ecx,edi
	mov	al,20h
	rep	stosb
	mov	edi,[esp]
	add	edi,1*2
	mov	ecx,30
	call	draw_static
	mov	edi,[esp]
	mov	al,[selected_character]
	mov	[gs:edi+12*2],al
      ascii_table_loop:
	call	wait_for_input
	or	ah,ah
	jz	pure_ascii_char
	cmp	ah,48h
	je	ascii_table_up
	cmp	ah,50h
	je	ascii_table_down
	cmp	ah,4Bh
	je	ascii_table_left
	cmp	ah,4Dh
	je	ascii_table_right
	cmp	ah,1
	je	ascii_table_exit
	cmp	al,0E0h
	je	ascii_table_loop
	cmp	al,13
	je	ascii_table_done
	cmp	al,2
	je	ascii_table_done
	cmp	al,20h
	jb	ascii_table_loop
      pure_ascii_char:
	mov	[selected_character],al
	jmp	ascii_table_update
      ascii_table_exit:
	pop	eax eax
	stc
	ret
      ascii_table_done:
	pop	eax eax
	mov	al,[selected_character]
	clc
	ret
      ascii_table_up:
	cmp	[selected_character],20h
	jb	ascii_table_loop
	sub	[selected_character],20h
	jmp	ascii_table_update
      ascii_table_down:
	cmp	[selected_character],0E0h
	jae	ascii_table_loop
	add	[selected_character],20h
	jmp	ascii_table_update
      ascii_table_left:
	test	[selected_character],11111b
	jz	ascii_table_loop
	dec	[selected_character]
	jmp	ascii_table_update
      ascii_table_right:
	mov	al,[selected_character]
	inc	al
	test	al,11111b
	jz	ascii_table_loop
	mov	[selected_character],al
	jmp	ascii_table_update
  calculator_window:
	mov	[results_selection],0
	mov	esi,_calculator
	mov	dx,0602h
	mov	cx,0B4Ch
	mov	ah,[window_colors]
	call	draw_window
	push	edi edx
	mov	eax,[video_pitch]
	lea	edi,[edi+eax+2*2]
	mov	esi,_expression
	mov	ecx,11
	call	draw_static
	mov	eax,[video_pitch]
	lea	eax,[eax*3]
	mov	edi,[esp+4]
	lea	edi,[edi+eax+2*2]
	mov	esi,_result
	mov	ecx,65
	call	draw_static
	call	init_common_dialog
	mov	ebx,buffer
	xor	esi,esi
	mov	ecx,56 + 1000 shl 16
	mov	dx,[esp]
	add	dx,010Eh
	mov	al,1
	call	create_edit_box
	call	register_box_in_dialog
	mov	ebx,buffer+2000h
	mov	esi,_null
	mov	edi,results_selection
	xor	ebp,ebp
	mov	dx,[esp]
	add	dx,0402h
	mov	cl,18h
	mov	al,2
	call	create_check_box
	call	register_box_in_dialog
	mov	ebx,buffer+2010h
	mov	esi,_null
	mov	edi,results_selection
	mov	ebp,1
	mov	dx,[esp]
	add	dx,0502h
	mov	cl,18h
	mov	al,2
	call	create_check_box
	call	register_box_in_dialog
	mov	ebx,buffer+2020h
	mov	esi,_null
	mov	edi,results_selection
	mov	ebp,2
	mov	dx,[esp]
	add	dx,0602h
	mov	cl,18h
	mov	al,2
	call	create_check_box
	call	register_box_in_dialog
	mov	ebx,buffer+2030h
	mov	esi,_null
	mov	edi,results_selection
	mov	ebp,3
	mov	dx,[esp]
	add	dx,0702h
	mov	cl,18h
	mov	al,2
	call	create_check_box
	call	register_box_in_dialog
	pop	edx edi
	mov	eax,[video_pitch]
	lea	edi,[edi+eax*4+6*2]
	mov	[results_offset],edi
	mov	[common_dialog_callback],calculate_result
      calculator_loop:
	call	common_dialog_loop
	jc	close_calculator
	mov	esi,[results_offset]
	mov	eax,[results_selection]
	imul	eax,[video_pitch]
	add	esi,eax
	mov	edi,buffer+16
      copy_result:
	lods	byte [gs:esi]
	cmp	al,20h
	je	result_ready
	stosb
	inc	esi
	jmp	copy_result
      result_ready:
	mov	ecx,edi
	sub	ecx,buffer+16
	mov	ebx,buffer
	mov	[ebx+8],cx
	mov	[ebx+12],cx
	xor	eax,eax
	mov	[ebx+10],ax
	mov	[ebx+14],ax
	cmp	[current_box],0
	jne	activate_expression_box
	call	draw_edit_box
	jmp	calculator_loop
      activate_expression_box:
	mov	edx,[current_box]
	mov	ebx,[boxes+edx*4]
	call	kill_box_focus
	mov	[current_box],0
	mov	ebx,buffer
	call	set_box_focus
	jmp	calculator_loop
      close_calculator:
	ret
      calculate_result:
	mov	esi,buffer+16
	movzx	eax,word [buffer+8]
	lea	edi,[esi+eax]
	xor	eax,eax
	stosb
	mov	[progress_offset],eax
	mov	[source_start],eax
	mov	[hash_tree],eax
	mov	[macro_status],al
	mov	[memory_end],buffer+1000h
	mov	[resume_esp],esp
	mov	[resume_eip],calculator_error
	call	convert_line
	push	edi
	call	convert_expression
	cmp	byte [esi],0
	jne	invalid_expression
	mov	al,')'
	stosb
	pop	esi
	mov	[value_size],8
	call	calculate_expression
	mov	ebp,edi
	mov	eax,[ebp]
	mov	edx,[ebp+4]
	mov	edi,buffer+3000h
	mov	word [edi],'b'
      make_binary_number:
	mov	bl,'0'
	shrd	eax,edx,1
	adc	bl,0
	dec	edi
	mov	[edi],bl
	shr	edx,1
	jnz	make_binary_number
	test	eax,eax
	jnz	make_binary_number
	mov	esi,edi
	mov	eax,[video_pitch]
	mov	edi,[results_offset]
	lea	edi,[edi+eax*2]
	mov	ecx,65
	call	draw_static
	mov	ecx,[ebp]
	mov	edx,[ebp+4]
	mov	edi,buffer+3000h
	mov	word [edi],'o'
      make_octal_number:
	mov	al,cl
	and	al,111b
	add	al,'0'
	dec	edi
	mov	[edi],al
	shrd	ecx,edx,3
	shr	edx,3
	jnz	make_octal_number
	test	ecx,ecx
	jnz	make_octal_number
	mov	esi,edi
	mov	eax,[video_pitch]
	mov	edi,[results_offset]
	lea	eax,[eax*3]
	add	edi,eax
	mov	ecx,65
	call	draw_static
	mov	ecx,[ebp]
	mov	edx,[ebp+4]
	mov	edi,buffer+3000h
	mov	word [edi],'h'
      make_hexadecimal_number:
	mov	al,cl
	and	al,0Fh
	cmp	al,10
	sbb	al,69h
	das
	dec	edi
	mov	[edi],al
	shrd	ecx,edx,4
	shr	edx,4
	jnz	make_hexadecimal_number
	test	ecx,ecx
	jnz	make_hexadecimal_number
	cmp	al,'A'
	jb	hexadecimal_number_ok
	dec	edi
	mov	byte [edi],'0'
      hexadecimal_number_ok:
	mov	esi,edi
	mov	eax,[video_pitch]
	mov	edi,[results_offset]
	lea	edi,[edi+eax]
	mov	ecx,65
	call	draw_static
	mov	edi,buffer+3000h
	mov	byte [edi],0
	mov	ecx,10
	xor	bl,bl
	test	byte [ebp+7],1 shl 7
	jz	make_decimal_number
	not	dword [ebp]
	not	dword [ebp+4]
	add	dword [ebp],1
	adc	dword [ebp+4],0
	mov	bl,'-'
      make_decimal_number:
	mov	eax,[ebp+4]
	xor	edx,edx
	div	ecx
	mov	[ebp+4],eax
	mov	eax,[ebp]
	div	ecx
	mov	[ebp],eax
	add	dl,'0'
	dec	edi
	mov	[edi],dl
	or	eax,[ebp+4]
	jnz	make_decimal_number
	test	bl,bl
	jz	decimal_number_ok
	dec	edi
	mov	[edi],bl
      decimal_number_ok:
	mov	esi,edi
	mov	edi,[results_offset]
	mov	ecx,65
	call	draw_static
	ret
      calculator_error:
	mov	ebx,[video_pitch]
	mov	ebp,[results_offset]
	mov	edx,4
      clear_results:
	mov	ecx,65
	mov	edi,ebp
	call	fill_static
	add	ebp,ebx
	dec	edx
	jnz	clear_results
	ret

; Memory allocation

  get_memory:
	push	esi edi
	mov	ebx,ecx
	shr	ebx,16
	mov	ax,501h
	int	31h
	jc	dpmi_allocation_failed
	mov	ax,bx
	shl	eax,16
	mov	ax,cx
	mov	edx,main
	shl	edx,4
	sub	eax,edx
	mov	bx,si
	shl	ebx,16
	mov	bx,di
	pop	edi esi
	ret
    dpmi_allocation_failed:
	xor	eax,eax
	pop	edi esi
	ret
  release_memory:
	push	esi edi
	mov	esi,ebx
	shr	esi,16
	mov	di,bx
	mov	ax,502h
	int	31h
	pop	edi esi
	ret
  get_low_memory:
	mov	ax,100h
	mov	bx,-1
	int	31h
	movzx	eax,bx
	shl	eax,4
	mov	[low_memory_size],eax
	mov	ax,100h
	int	31h
	mov	[low_memory_selector],dx
	jnc	low_memory_ok
	xor	edx,edx
	mov	[low_memory_size],edx
      low_memory_ok:
	ret
  release_low_memory:
	cmp	[low_memory_size],0
	je	low_memory_ok
	mov	ax,101h
	mov	dx,[low_memory_selector]
	int	31h
	ret

; File operations

  dos_int:
	push	0 0 0
	pushw	buffer_segment buffer_segment
	stc
	pushfw
	push	eax
	push	ecx
	push	edx
	push	ebx
	push	0
	push	ebp
	push	esi
	push	edi
	mov	ax,300h
	mov	bx,21h
	xor	cx,cx
	mov	edi,esp
	push	es ss
	pop	es
	int	31h
	pop	es
	mov	edi,[esp]
	mov	esi,[esp+4]
	mov	ebp,[esp+8]
	mov	ebx,[esp+10h]
	mov	edx,[esp+14h]
	mov	ecx,[esp+18h]
	mov	ah,[esp+20h]
	add	esp,32h
	sahf
	mov	eax,[esp-32h+1Ch]
	ret
  open:
	push	esi edi
	call	adapt_path
	mov	ax,716Ch
	mov	bx,100000b
	mov	dx,1
	xor	cx,cx
	xor	si,si
	call	dos_int
	jnc	open_done
	cmp	ax,7100h
	je	old_open
	stc
	jmp	open_done
      old_open:
	mov	ax,3D00h
	xor	dx,dx
	call	dos_int
      open_done:
	mov	bx,ax
	pop	edi esi
	ret
    adapt_path:
	mov	esi,edx
	mov	edi,buffer
      copy_path:
	lodsb
	cmp	al,'/'
	jne	path_char_ok
	mov	al,'\'
      path_char_ok:
	stosb
	or	al,al
	jnz	copy_path
	ret
  create:
	push	esi edi
	call	adapt_path
	mov	ax,716Ch
	mov	bx,100001b
	mov	dx,10010b
	xor	cx,cx
	xor	si,si
	xor	di,di
	call	dos_int
	jnc	create_done
	cmp	ax,7100h
	je	old_create
	stc
	jmp	create_done
    old_create:
	mov	ah,3Ch
	xor	cx,cx
	xor	dx,dx
	call	dos_int
    create_done:
	mov	bx,ax
	pop	edi esi
	ret
  write:
	push	edx esi edi ebp
	mov	ebp,ecx
	mov	esi,edx
      write_loop:
	mov	ecx,1000h
	sub	ebp,1000h
	jnc	do_write
	add	ebp,1000h
	mov	ecx,ebp
	xor	ebp,ebp
      do_write:
	push	ecx
	mov	edi,buffer
	shr	ecx,2
	rep	movsd
	mov	ecx,[esp]
	and	ecx,11b
	rep	movsb
	pop	ecx
	mov	ah,40h
	xor	dx,dx
	call	dos_int
	or	ebp,ebp
	jnz	write_loop
	pop	ebp edi esi edx
	ret
  read:
	push	edx esi edi ebp
	mov	ebp,ecx
	mov	edi,edx
      read_loop:
	mov	ecx,1000h
	sub	ebp,1000h
	jnc	do_read
	add	ebp,1000h
	mov	ecx,ebp
	xor	ebp,ebp
      do_read:
	push	ecx
	mov	ah,3Fh
	xor	dx,dx
	call	dos_int
	cmp	ax,cx
	jne	eof
	mov	esi,buffer
	mov	ecx,[esp]
	shr	ecx,2
	rep	movsd
	pop	ecx
	and	ecx,11b
	rep	movsb
	or	ebp,ebp
	jnz	read_loop
      read_done:
	pop	ebp edi esi edx
	ret
      eof:
	pop	ecx
	stc
	jmp	read_done
  close:
	mov	ah,3Eh
	int	21h
	ret
  lseek:
	mov	ah,42h
	mov	ecx,edx
	shr	ecx,16
	int	21h
	pushf
	shl	edx,16
	popf
	mov	dx,ax
	mov	eax,edx
	ret

; Other functions needed by assembler core

  get_environment_variable:
	push	esi edi
	mov	ebx,_section_environment
	call	get_ini_value
	pop	edi ebx
	jnc	found_value_in_ini
	push	ds
	mov	ds,[environment_selector]
	xor	esi,esi
      compare_variable_names:
	mov	edx,ebx
      compare_name_char:
	lodsb
	mov	ah,[es:edx]
	inc	edx
	cmp	al,'='
	je	end_of_variable_name
	or	ah,ah
	jz	next_variable
	sub	ah,al
	jz	compare_name_char
	cmp	ah,20h
	jne	next_variable
	cmp	al,41h
	jb	next_variable
	cmp	al,5Ah
	jna	compare_name_char
      next_variable:
	lodsb
	or	al,al
	jnz	next_variable
	cmp	byte [esi],0
	jne	compare_variable_names
	pop	ds
	ret
      end_of_variable_name:
	or	ah,ah
	jnz	next_variable
      copy_variable_value:
	lodsb
	cmp	edi,[es:memory_end]
	jae	out_of_memory
	stosb
	or	al,al
	jnz	copy_variable_value
	dec	edi
	pop	ds
	ret
      found_value_in_ini:
	lea	eax,[edi+ecx]
	cmp	eax,[memory_end]
	jae	out_of_memory
	rep	movsb
	ret
  make_timestamp:
	mov	ah,2Ah
	int	21h
	push	dx cx
	movzx	ecx,cx
	mov	eax,ecx
	sub	eax,1970
	mov	ebx,365
	mul	ebx
	mov	ebp,eax
	mov	eax,ecx
	sub	eax,1969
	shr	eax,2
	add	ebp,eax
	mov	eax,ecx
	sub	eax,1901
	mov	ebx,100
	div	ebx
	sub	ebp,eax
	mov	eax,ecx
	xor	edx,edx
	sub	eax,1601
	mov	ebx,400
	div	ebx
	add	ebp,eax
	movzx	ecx,byte [esp+3]
	mov	eax,ecx
	dec	eax
	mov	ebx,30
	mul	ebx
	add	ebp,eax
	cmp	ecx,8
	jbe	months_correction
	mov	eax,ecx
	sub	eax,7
	shr	eax,1
	add	ebp,eax
	mov	ecx,8
      months_correction:
	mov	eax,ecx
	shr	eax,1
	add	ebp,eax
	cmp	ecx,2
	pop	cx
	jbe	day_correction_ok
	sub	ebp,2
	test	ecx,11b
	jnz	day_correction_ok
	xor	edx,edx
	mov	eax,ecx
	mov	ebx,100
	div	ebx
	or	edx,edx
	jnz	day_correction
	mov	eax,ecx
	mov	ebx,400
	div	ebx
	or	edx,edx
	jnz	day_correction_ok
      day_correction:
	inc	ebp
      day_correction_ok:
	pop	dx
	movzx	eax,dl
	dec	eax
	add	eax,ebp
	mov	ebx,24
	mul	ebx
	push	eax
	mov	ah,2Ch
	int	21h
	pop	eax
	push	dx
	movzx	ebx,ch
	add	eax,ebx
	mov	ebx,60
	mul	ebx
	movzx	ebx,cl
	add	eax,ebx
	mov	ebx,60
	mul	ebx
	pop	bx
	movzx	ebx,bh
	add	eax,ebx
	adc	edx,0
	ret
  display_block:
	mov	edi,[display_length]
	mov	eax,[display_length]
	add	eax,ecx
	cmp	eax,[low_memory_size]
	ja	not_enough_memory
	mov	[display_length],eax
	push	es
	mov	es,[low_memory_selector]
	rep	movsb
	pop	es
	ret

; Error handling

  not_enough_memory:
	call	update_screen
	mov	esi,_memory_error
	mov	ebx,_error
	movzx	eax,[error_box_colors]
	call	message_box
	mov	esp,stack_top
	jmp	main_loop

  fatal_error:
	cmp	[progress_offset],0
	je	error_outside_compiler
	pop	esi
	mov	esp,stack_top
	push	esi
	mov	ax,205h
	mov	bl,9
	mov	edx,dword [keyboard_handler]
	mov	cx,word [keyboard_handler+4]
	int	31h
	call	show_display_buffer
	mov	ebx,[allocated_memory]
	call	release_memory
	call	update_screen
      show_error_summary:
	mov	esi,buffer+3000h
	call	go_to_directory
	mov	esi,_assembler_error
	mov	edi,buffer
	mov	ebx,esp
	call	sprintf
	mov	esi,buffer
	mov	ebx,_compile
	movzx	eax,[error_box_colors]
	mov	[first_button],_ok
	mov	[second_button],_get_display
	cmp	[display_length],0
	je	show_compilation_summary
	or	eax,2000000h
	jmp	show_compilation_summary
  assembler_error:
	cmp	[progress_offset],0
	je	error_outside_compiler
	pop	esi
	mov	esp,stack_top
	push	esi
	mov	ax,205h
	mov	bl,9
	mov	edx,dword [keyboard_handler]
	mov	cx,word [keyboard_handler+4]
	int	31h
	call	show_display_buffer
	call	update_screen
	mov	ebx,[current_line]
      find_error_origin:
	test	dword [ebx+4],80000000h
	jz	error_origin_found
	mov	ebx,[ebx+8]
	jmp	find_error_origin
      error_origin_found:
	mov	esi,[ebx]
	mov	edi,filename_buffer
      copy_error_file:
	lodsb
	stosb
	or	al,al
	jnz	copy_error_file
	push	dword [ebx+4]
	mov	ebx,[allocated_memory]
	call	release_memory
	mov	edx,filename_buffer
	call	load_file
      show_error_line:
	pop	eax
	call	find_line
	xor	eax,eax
	mov	[selection_line],esi
	mov	[selection_line_number],ecx
	mov	[selection_position],eax
	mov	[caret_position],eax
	push	esi
	lea	edi,[esi+SEGMENT_HEADER_LENGTH]
	lea	ebp,[esi+SEGMENT_LENGTH]
	mov	ebx,characters
	xor	edx,edx
      check_for_more_lines:
	call	peek_character
	jc	no_more_lines
	cmp	al,3Bh
	je	no_more_lines
	mov	ah,al
	xlatb
	or	al,al
	jz	symbol
	or	edx,edx
	jnz	neutral
	cmp	ah,27h
	je	quoted
	cmp	ah,22h
	je	quoted
      neutral:
	or	edx,-1
	jmp	check_for_more_lines
      peek_character:
	cmp	edi,ebp
	je	peek_next_segment
	mov	al,[edi]
	inc	edi
	clc
	ret
      peek_next_segment:
	mov	esi,[esi]
	btr	esi,0
	lea	edi,[esi+SEGMENT_HEADER_LENGTH]
	lea	ebp,[esi+SEGMENT_LENGTH]
	jc	peek_character
	stc
	ret
      symbol:
	cmp	ah,'\'
	je	backslash
	xor	edx,edx
	jmp	check_for_more_lines
      quoted:
	call	peek_character
	jc	no_more_lines
	cmp	al,ah
	jne	quoted
	call	peek_character
	jc	no_more_lines
	cmp	al,ah
	je	quoted
	dec	edi
	xor	edx,edx
	jmp	check_for_more_lines
      backslash:
	call	peek_character
	jc	more_lines
	cmp	al,20h
	je	backslash
	cmp	al,3Bh
	jne	no_more_lines
      comment:
	mov	esi,[esi]
	btr	esi,0
	jc	comment
      more_lines:
	or	esi,esi
	jz	last_line
	inc	ecx
	mov	[esp],esi
	jmp	check_for_more_lines
      last_line:
	pop	[caret_line]
	mov	[caret_line_number],ecx
	mov	eax,[maximum_position]
	mov	[caret_position],eax
	jmp	error_line_highlighted
      no_more_lines:
	or	esi,esi
	jz	last_line
	pop	eax
	inc	ecx
	mov	[caret_line],esi
	mov	[caret_line_number],ecx
      error_line_highlighted:
	call	let_caret_appear
	mov	eax,[caret_line]
	xchg	eax,[selection_line]
	mov	[caret_line],eax
	mov	eax,[caret_line_number]
	xchg	eax,[selection_line_number]
	mov	[caret_line_number],eax
	mov	eax,[caret_position]
	xchg	eax,[selection_position]
	mov	[caret_position],eax
	call	let_caret_appear
	call	update_window
	call	update_screen
	jmp	show_error_summary
      error_outside_compiler:
	mov	esp,[resume_esp]
	jmp	[resume_eip]

; Assembler core

  include '..\..\errors.inc'
  include '..\..\symbdump.inc'
  include '..\..\preproce.inc'
  include '..\..\parser.inc'
  include '..\..\exprpars.inc'
  include '..\..\assemble.inc'
  include '..\..\exprcalc.inc'
  include '..\..\formats.inc'
  include '..\..\x86_64.inc'
  include '..\..\avx.inc'

; Assembler constants

  include '..\..\tables.inc'
  include '..\..\messages.inc'
  include '..\..\version.inc'

; String constants

  _caption db 'flat assembler ',VERSION_STRING,0
  _copyright db 'Copyright (c) 1999-2011, Tomasz Grysztar',0

  _null db 0
  _untitled db 'Untitled',0
  _compile db 'Compile',0
  _error db 'Error',0
  _ok db 'OK',0
  _yes db 'Yes',0
  _no db 'No',0
  _get_display db 'Get display to clipboard',0
  _open db 'Open',0
  _save_as db 'Save as',0
  _file db 'File:',0
  _position db 'Position',0
  _row db 'Row:',0
  _column db 'Column:',0
  _find db 'Find',0
  _replace db 'Replace',0
  _text_to_find db 'Text to find:',0
  _new_text db 'New text:',0
  _expression db 'Expression:',0
  _result db 'Result:',0
  _case_sensitive db 'Case sensitive',0
  _whole_words db 'Whole words',0
  _backward db 'Backward search',0
  _prompt db 'Prompt on replace',0
  _options db 'Editor options',0
  _secure_selection db 'Secure selection',0
  _auto_brackets db 'Automatic brackets',0
  _auto_indent db 'Automatic indents',0
  _smart_tabs db 'Smart tabulation',0
  _optimal_fill db 'Optimal fill on saving',0
  _ascii_table db 'ASCII table',0
  _calculator db 'Calculator',0

  _startup_failed db 'Failed to allocate required memory.',0
  _memory_error db 'Not enough memory to complete this operation.',0
  _loading_error db 'Could not load file %s.',0
  _saving_error db 'Could not write file to disk.',0
  _not_executable db 'Cannot execute this kind of file.',0
  _saving_question db 'File was modified. Save it now?',0
  _overwrite_question db 'File %s already exists. Do you want to replace it?',0
  _directory_question db 'Directory %s does not exist. Do you want to create it now?',0
  _directory_error db 'Failed to create the directory.',0
  _invalid_path db 'Invalid path.',0
  _not_found_after db 'Text %s not found after current position.',0
  _not_found_before db 'Text %s not found before current position.',0
  _replace_prompt db 'Replace this occurence?',0
  _replaces_made db '%d replaces made.',0
  _assembler_error db 'Error: %s.',0

  _section_environment db 'Environment',0
  _section_compiler db 'Compiler',0
  _key_compiler_memory db 'Memory',0
  _key_compiler_passes db 'Passes',0
  _section_options db 'Options',0
  _key_options_securesel db 'SecureSelection',0
  _key_options_autobrackets db 'AutoBrackets',0
  _key_options_autoindent db 'AutoIndent',0
  _key_options_smarttabs db 'SmartTabs',0
  _key_options_optimalfill db 'OptimalFill',0
  _section_colors db 'Colors',0
  _key_color_text db 'Text',0
  _key_color_background db 'Background',0
  _key_color_seltext db 'SelectionText',0
  _key_color_selbackground db 'SelectionBackground',0
  _key_color_symbols db 'Symbols',0
  _key_color_numbers db 'Numbers',0
  _key_color_strings db 'Strings',0
  _key_color_comments db 'Comments',0
  _key_color_statustext db 'StatusText',0
  _key_color_statusbackground db 'StatusBackground',0
  _key_color_wintext db 'WindowText',0
  _key_color_winbackground db 'WindowBackground',0
  _key_color_msgtext db 'MessageText',0
  _key_color_msgbackground db 'MessageBackground',0
  _key_color_msgseltext db 'MessageSelectionText',0
  _key_color_msgselbackground db 'MessageSelectionBackground',0
  _key_color_errtext db 'ErrorText',0
  _key_color_errbackground db 'ErrorBackground',0
  _key_color_errseltext db 'ErrorSelectionText',0
  _key_color_errselbackground db 'ErrorSelectionBackground',0
  _key_color_boxtext db 'BoxText',0
  _key_color_boxbackground db 'BoxBackground',0
  _key_color_boxseltext db 'BoxSelectionText',0
  _key_color_boxselbackground db 'BoxSelectionBackground',0

; Configuration

  editor_style dd AES_AUTOINDENT+AES_SMARTTABS+AES_SECURESEL+AES_OPTIMALFILL

  text_colors db 87h
  selection_colors db 7Fh
  symbol_color db 0Fh
  number_color db 0Ah
  string_color db 0Ch
  comment_color db 3
  status_colors db 2Fh
  window_colors db 3Fh
  box_colors db 1Fh
  box_selection_colors db 9Fh
  message_box_colors dw 3F1Fh
  error_box_colors dw 4E6Eh

; Other constants

  browser_symbols db 18h,09h,07h,0F0h

; Assembly Editor core

  include '..\memory.inc'
  include '..\navigate.inc'
  include '..\edit.inc'
  include '..\blocks.inc'
  include '..\search.inc'
  include '..\undo.inc'

; Assembly Editor constants

  SEGMENT_LENGTH	= 160
  BLOCK_LENGTH		= 1024 * SEGMENT_LENGTH
  SEGMENT_HEADER_LENGTH = 16
  SEGMENT_DATA_LENGTH	= SEGMENT_LENGTH - SEGMENT_HEADER_LENGTH

  AEMODE_OVERWRITE   = 1
  AEMODE_VERTICALSEL = 2

  AEFIND_CASESENSITIVE = 1
  AEFIND_WHOLEWORDS    = 2
  AEFIND_BACKWARD      = 4

  AES_AUTOINDENT   = 0001h
  AES_AUTOBRACKETS = 0002h
  AES_SMARTTABS    = 0004h
  AES_SECURESEL    = 0008h
  AES_OPTIMALFILL  = 0010h

; Assembly Editor data

  editor_data:

  next_instance dd ?
  previous_instance dd ?
  file_path dd ?
  file_path_handle dd ?
  unmodified_state dd ?

  include '..\variable.inc'

  editor_data_size = $ - editor_data

  if editor_data_size > SEGMENT_DATA_LENGTH
    err
  end if

  lower_case_table db 100h dup ?
  upper_case_table db 100h dup ?

; Assembler core data

  include '..\..\variable.inc'

; Interface specific data

  psp_selector dw ?
  environment_selector dw ?
  main_selector dw ?
  bios_selector dw ?
  video_selector dw ?

  screen_width dd ?
  screen_height dd ?
  video_pitch dd ?

  video_storage dd ?
  video_storage_handle dd ?
  stored_cursor dw ?
  stored_cursor_position dw ?
  stored_page db ?
  stored_mode db ?

  low_memory_size dd ?
  low_memory_selector dw ?

  last_operation db ?
  current_operation db ?
  was_selection db ?

  line_buffer dd ?
  line_buffer_size dd ?
  line_buffer_handle dd ?
  screen_offset dd ?
  screen_row_buffer db 512 dup ?

  clipboard dd ?
  clipboard_handle dd ?

  main_project_file dd ?
  memory_limit dd ?
  allocated_memory dd ?
  start_time dd ?
  progress_offset dd ?
  keyboard_handler dp ?
  display_length dd ?

  find_flags dd ?
  replaces_count dd ?
  selected_character db ?
  command_flags db ?
  message_width db ?
  buttons_width db ?
  first_button dd ?
  second_button dd ?

  file_handle dd ?
  filename_buffer db 17+256 dup ?

  ini_data dd ?
  ini_data_handle dd ?
  ini_data_length dd ?
  ini_path db 260 dup ?

  file_list dd ?
  file_list_buffer dd ?
  file_list_buffer_top dd ?
  file_list_buffer_handle dd ?
  file_list_buffer_size dd ?

  current_box dd ?
  boxes_count dd ?
  boxes dd 16 dup ?
  common_dialog_callback dd ?

  resume_esp dd ?
  resume_eip dd ?
  results_offset dd ?
  results_selection dd ?

segment buffer_segment

  buffer = (buffer_segment-main) shl 4

  db 4000h dup ?

segment stack_segment

  stack_bottom = (stack_segment-main) shl 4

  db 4000h dup ?

  stack_top = stack_bottom + $
