init_cmd_hist_buffer:
;-------------------------------------------------------------------------------
	push	eax ebx ecx

	mcall	68, 12, 4096	;allocate 4KB block
	mov	[cmd_hist_buffer.ptr], eax
	mov	[cmd_hist_buffer.size], ecx

	mov	edi, eax
	xor	eax, eax
	stosd
	stosd
	mov	[cmd_hist_buffer.new_node_offset], eax
	mov	[cmd_hist_buffer.last_node_offset], eax
	mov	[cmd_hist_buffer.cur_node_offset], eax
	mov	[cmd_hist_buffer.tmp_line_flag], al
	mov	[cmd_hist_buffer.n_flag], al

	pop	ecx ebx eax
	ret
;-------------------------------------------------------------------------------

enlarge_cmd_hist_buffer:
;-------------------------------------------------------------------------------
	pusha

	mov	ecx, [cmd_hist_buffer.size]
	add	ecx, 4096
	mov	edx, [cmd_hist_buffer.ptr]
	mcall	68, 20		;reallocate the buffer (prev. size + 4KB)
	test	eax, eax
	jz	.err
	mov	[cmd_hist_buffer.ptr], eax
	mov	[cmd_hist_buffer.size], ecx

.ok:
	clc
	popa
	ret

.err:
	stc
	popa
	ret
;-------------------------------------------------------------------------------

add_cmd_hist_line:
;-------------------------------------------------------------------------------
;in:
;eax = ptr to ASCIIZ string of line
;-------------------------------------------------------------------------------
	pusha

	mov	esi, eax
	mov	edx, eax
	xor	ecx, ecx

@@:
	inc	ecx
	lodsb
	test	al, al
	jz	@f
	jmp	@b

@@:
	dec	ecx
	jz	.ok

	inc	ecx

	mov	eax, [cmd_hist_buffer.new_node_offset]
	lea	eax, [eax+ecx+2*4]
	cmp	[cmd_hist_buffer.size], eax
	jae	@f
	call	enlarge_cmd_hist_buffer
	jc	.err

@@:
	mov	edi, [cmd_hist_buffer.new_node_offset]
	mov	eax, [cmd_hist_buffer.ptr]
	add	edi, eax
	cmp	eax, edi		;if eax = edi, then it's the first node
	jne	@f
	xor	eax, eax
	dec	eax
	stosd				;save previous node link = -1 for the first node
	stosd				;save next node link = -1 for the first node
	jmp	.cp_str

@@:
	mov	ebx, [cmd_hist_buffer.last_node_offset]
	mov	[edi], ebx		;save previous node link for a new node
	add	ebx, eax
	mov	eax, [cmd_hist_buffer.new_node_offset]
	mov	[ebx+4], eax		;update next node link for a last node
	mov	[cmd_hist_buffer.last_node_offset], eax
	mov	[cmd_hist_buffer.cur_node_offset], eax
	add	edi, 4
	xor	eax, eax
	dec	eax
	stosd

.cp_str:
	mov	esi, edx

	push	ecx
	rep	movsb
	pop	ecx

	add	ecx, 2*4
	add	[cmd_hist_buffer.new_node_offset], ecx


.ok:
	clc

.err:
	mov	[cmd_hist_buffer.tmp_line_flag], 0

	popa
	ret
;-------------------------------------------------------------------------------

add_cmd_hist_tmp_line:
;-------------------------------------------------------------------------------
;in:
;eax = ptr to ASCIIZ string of line
;-------------------------------------------------------------------------------
	pusha

	mov	esi, eax
	mov	edx, eax
	xor	ecx, ecx

@@:
	inc	ecx
	lodsb
	test	al, al
	jz	@f
	jmp	@b

@@:
	mov	eax, [cmd_hist_buffer.new_node_offset]
	lea	eax, [eax+ecx+2*4]
	cmp	[cmd_hist_buffer.size], eax
	jae	@f
	call	enlarge_cmd_hist_buffer
	jc	.err

@@:
	mov	edi, [cmd_hist_buffer.new_node_offset]
	mov	[cmd_hist_buffer.tmp_line_flag], 1
	mov	eax, [cmd_hist_buffer.ptr]
	add	edi, eax
	xor	eax, eax
	stosd
	stosd		;two zeroes - marker (prefix) of tmp line

.cp_str:
	mov	esi, edx

	rep	movsb

.ok:
	clc

.err:
	popa
	ret
;-------------------------------------------------------------------------------

get_cmd_hist_line:
;-------------------------------------------------------------------------------
;out:
;eax = ptr to ASCIIZ string of current line
;-------------------------------------------------------------------------------
	push	ebx

	mov	eax, [cmd_hist_buffer.ptr]
	mov	ebx, [cmd_hist_buffer.cur_node_offset]

	lea	eax, [eax + ebx + 2*4]

	pop	ebx
	ret
;-------------------------------------------------------------------------------

get_cmd_hist_tmp_line:
;-------------------------------------------------------------------------------
;out:
;eax = ptr to ASCIIZ string of current line or 0 (no tmp line)
;-------------------------------------------------------------------------------
	cmp	[cmd_hist_buffer.tmp_line_flag], 0
	je	@f

	mov	eax, [cmd_hist_buffer.new_node_offset]
	add	eax, [cmd_hist_buffer.ptr]
	add	eax, 2*4

@@:
	ret
;-------------------------------------------------------------------------------

prev_cmd_hist_line:
;-------------------------------------------------------------------------------
;out:
;CF = 0 - OK, CF = 1 (no previous lines)
;-------------------------------------------------------------------------------
	push	eax ebx

	mov	eax, [cmd_hist_buffer.ptr]
	mov	ebx, [cmd_hist_buffer.cur_node_offset]

	lea	eax, [eax+ebx]
	mov	eax, [eax]
	inc	eax
	jz	.ret_cf
	dec	eax
	mov	[cmd_hist_buffer.cur_node_offset], eax

	clc
	pop	ebx eax
	ret

.ret_cf:
	stc
	pop	ebx eax
	ret
;-------------------------------------------------------------------------------

next_cmd_hist_line:
;-------------------------------------------------------------------------------
;out:
;CF = 0 - OK, CF = 1 (no next lines)
;-------------------------------------------------------------------------------
	push	eax ebx

	mov	eax, [cmd_hist_buffer.ptr]
	mov	ebx, [cmd_hist_buffer.cur_node_offset]

	lea	eax, [eax+ebx]
	mov	eax, [eax+4]
	inc	eax
	jz	.ret_cf
	dec	eax
	mov	[cmd_hist_buffer.cur_node_offset], eax

	clc
	pop	ebx eax
	ret

.ret_cf:
	stc
	pop	ebx eax
	ret
;-------------------------------------------------------------------------------