; Расчитана на функцию #32 ДОС с новым курсором.
;

; Функция строки редактирования. Имеет историю вводимых строк.
; Функция использует для своей работы временный буфер:
;
;       Buffers.work.buffer      -  этот буфер использует история
;	;Buffers.work.buffer+256  -  возвращается набранная строка
;
; Клавиши:
;   Esc     - сбросить текущую строку
;   Enter   - выход из функции (в Buffers.work.buffer+256 готовая строка)
;   Ins     - смена режима ввода (вставка/замена)
;   , курсор - прокрутка истории
;   PageUp     - в начало истории
;   PageDown   - в конец истории
;   Ctrl+Del   - стереть историю
;
;
; Используется как заготовка для шелла ДОС. Выводит системный путь.
; Макс. длина экран. пути 34 символа (с диском), остальное обрезается.
;




;true		equ	1
;false		equ	0

max_screen_path	equ	32		; макс. длина экран. пути (без диска)
max_len_comline	equ	254		; макс. длина ком-строки (больше не делать)
history_size	equ	256		; размер history-буфера

; события (внутренние)
evNothing	equ	0		; нет событий
evKeyboard	equ	1		; нажата обычная клавиша
evCombKey	equ	2		; нажата комбин. клавиш или курсорные






;===========================================================
; Строка редактирования
;
; Выход из строки по клавише <Enter>,
; ;в Buffers.work.buffer+256 = набранная строка (или пустая)
;===========================================================
input_line:
	ld	a,1
	ld	(insert_mode),a
	ld	c,BIOS.LP_GET_PLACE	; узнать полож. курсора
	RST	ToBIOS
	ld	e,4			; X начало
	ld	(YXpos),de		; Y/X начало ком-строки
	ld	(cursor_position),de	; Y/X позиция курсора
	call	clear_inpline		; очистить структуру ~input line~
	call	print_compath		; вывести путь + новая ширина поля ввода
	jp	event_input_line	; на обраб. строки ввода




;---------------------------------------------------------------
; Вывод пути в ком-строке на экран + новая ширина поля ввода
;---------------------------------------------------------------
print_compath:
	ld	hl,Buffers.sys_path		; сист. путь
	ld	de,Buffers.screen_path+2	; буфер для короткого пути
	call	make_short_path
	xor	a
	ld	(de),a			; зануление строки
	ex	af,af'			; восст. длину строки
	add	a,2			; + длина "X:"
	ld	b,a
	inc	a
	ld	(YXpos),a		; X начало ком-строки
	ld	a,width_inpline.MAX-1	; ширина экрана - 1
	sub	b
	ld	(width_inpline),a	; новая ширина поля ввода (76..48)
	push	bc
	; очистить экран. строку
	ld	de,(cursor_position)	; Y/X полож.
	ld	e,0
	ld	hl,#0150		; Y/X размер
	ld	a,(color_screen)	; атрибут
	ld	b,a
	ld	a," "			; символ очистки
	ld	c,BIOS.LP_CLS_WIN2	; очистить окно
	RST	ToBIOS
	pop	bc
	; вывести экран. путь
	ld	hl,Buffers.screen_path	; экран. путь
	;call	print_inpchar		; вывод строки по счетчику
	ld	c,BIOS.LP_PRINT_LINE2
	RST	ToBIOS;
	ld	a,">"
	ld	bc,1*256 + BIOS.LP_PRINT_SYM	; символ без атрибута
	RST	ToBIOS
	;jr	print_inpline		; вывод строки ввода
	;-------------------------------------------------
	; Вывод строки ~input line~ на экран
	;-------------------------------------------------
print_inpline:
	ld	de,(YXpos)			; Y/X начало ком-строки
	ld	c,Dss.Locate			; уст. курсор
	RST	ToDSS
	ld	hl,Buffers.input_line		; структура буфера ~input line~
	push	hl
	pop	iy
	ld	a,(iy + Input_Line.Left_Shift)	;+3 смещ. строки за левый край
	add	a,l
	ld	l,a
	jr	nc,$+3				; !FIXIT
	inc	h
	inc	hl
	inc	hl
	inc	hl
	inc	hl
	inc	hl
	ld	a,(width_inpline)		; ширина поля
	ld	c,a
	ld	b,a
	push	bc
	xor	a
	ld	de,Buffers.work.buffer			; врем. буфер
	push	de
	ld	(de),a
	inc	de
	djnz	$-2				; !FIXIT
	ld	a,(iy + Input_Line.max_Len)
	sub	(iy + Input_Line.Left_Shift)
	cp	c
	jr	nc,$+3				; !FIXIT
	ld	c,a
	ld	a,(iy + Input_Line.Symbols_Num)	; число введ. символов
	sub	c
	jr	nc,$+4				; !FIXIT
	add	a,c
	ld	c,a
	pop	de
	push	de
	ld	a,b
	or	c
	jr	z,$+4				; !FIXIT
	ldir
	pop	hl
	pop	bc
	ld	a,b				; длина строки
	or	a
	;call	nz,print_inpchar		; вывод строки по счетчику
	ld	c,BIOS.LP_PRINT_LINE2
	call	nz,ToBIOS
	ld	a,(YXpos)			; X начало ком-строки
	ld	e,(iy + Input_Line.Cur_X)	;+2 тек. полож. курсора в строке
	add	a,e
	cp	width_inpline.MAX		; ширина экрана
	jr	c,prne1__
	ld	b,width_inpline.MAX-1
	sub	b
	ld	d,a				; "наезд" за правый край
	ld	a,e
	sub	d
	ld	(iy + Input_Line.Cur_X),a	;+2 новое полож. курсора
	ld	a,b
prne1__:ld	(cursor_position),a		; X полож. курсора на экране
	ret

; вход: HL - полный путь
;	DE - буфер для короткой строки пути
make_short_path:; узнать длину сист. пути
		ld	(.bufferAddr),de
		ld	e,l
		ld	d,h
		ld	bc,max_len_comline	; 254
		xor	a
		ld	(.flag),a	; сбр. флаг
		cpir
		dec	hl
		push	hl			; сохр. конец пути
		sbc	hl,de
		ld	a,l			; длина строки
		cp	max_screen_path+1	; 33
		jr	c,.copy
		; длина пути > 32
		ld	a,max_screen_path	; 32
		ld	(.flag),a	; уст. флаг
.copy:		ld	c,a			; полная длина строки
		ld	b,0
		ex	af,af'			; сохр. длину строки
		pop	hl			; восст. конец пути
.bufferAddr+1:	ld	de,0			; куда
		; скопировать строку
		and	a
		sbc	hl,bc			; hl=начало перекачки
		ldir
.flag+1:	ld	a,0			; флаг переполн. строки
		or	a
		ret	z
		ld	hl,(.bufferAddr)
		ld	(hl),'\' 
		inc	hl
		ld	a,"."
		ld	(hl),a
		inc	hl
		ld	(hl),a
		ret

; Вывод строки по счетчику
;print_inpchar:
	;ld	a,(hl)
	;inc	hl
	;push	hl
	;push	bc
	;ld	bc,0182h
	;RST	ToBIOS
;	ld	c,86h
;	RST	ToBIOS
	;pop	bc
	;pop	hl
	;djnz	print_inpchar
;	ret




;-------------------------------------------------
; Чтение событий
;-------------------------------------------------
handle_event:
cursor_position+1:
	ld	de,0
	;
	ld	c,Dss.Locate
	RST	ToDSS
	ld	c,Dss.EchoKey		; опрос клавы
	RST	ToDSS
	ld	hl,what			; поле событий
	ld	a,e
	or	a
	jr	z,handle_event_comb
	ld	(hl),evKeyboard		;+0 событие
	inc	hl
	ld	(hl),e			;+1 код клавиши
	inc	hl
	ld	(hl),d			;+2 скен-код клавиши
	ret
handle_event_comb:
	ld	(hl),evCombKey		;+0 событие
	inc	hl
	ld	(hl),b			;+1 флаги клавы
	inc	hl
	ld	(hl),d			;+2 код курс. клавиш
	ret

; поле событий
what:	ds	3

step_scroll	equ	1		; шаг X скроллинга строки


;=================================================
; Обработчик событий ~Input Line~
;=================================================
event_input_line:
	call	handle_event			; читаем событие
	ld	hl,event_input_line
	push	hl
	ld	iy,Buffers.input_line		; структура буфера ~input line~
	ld	hl,what				; список событий
	ld	a,(hl)
	inc	hl
	cp	evKeyboard
	jr	z,EvComKeys
	cp	evCombKey
	jp	z,EvComComb
	ret

; <Enter>
Enter:	pop	hl			; восст. баланс стека (выход из обработчика)
	xor	a
	;ld	(Buffers.work.buffer+256),a	; задать пустую строку
	ld	hl,Buffers.input_line.Symbols_Num	; число введ. символов
	ld	e,(hl)
	cp	e
	ret	z			; пустая строка
	ld	c," "			; пробел
	ld	d,a
	add	hl,de
	ld	a,(hl)
	cp	c
	jr	nz,ent1__		; нет конц. пробелов
	ld	b,e
	; убрать конц. пробелы ком-строки
	ld	a,(hl)
	cp	c
	jr	nz,$+8			;!FIXIT $
	dec	hl
	dec	(iy+4)			; --число введ. символов
	djnz	$-8			;!FIXIT $
	inc	hl
	ld	(hl),d			; в конец ком-строки
	ld	a,b
	or	a
	ret	z			; были одни пробелы
	ld	de,Buffers.input_line.Symbols_Num	; число введ. символов
	ld	(de),a			; новое число (для history_adding)
ent1__:	call	history_adding		; добавить строку в history
	; скопир. строку во врем. буфер
;	ld	hl,Buffers.input_line.Symbols_Num	; откуда
;	ld	de,Buffers.work.buffer+254	; куда
;	ld	a,(hl)			; скопир. строку (с нулем)
;	ldi
;	or	a
;	jr	nz,$-4
	;call	clear_input_line	; очистить строку ввода
;	ld	a,(YXpos+1);		; Y начало ком-строки
;	inc	a
;	cp	32
;	jr	c,$+3
;	xor	a
;	ld	(YXpos+1),a;
	; восст. буфер
;	ld	hl,Buffers.work.buffer+254	; откуда
;	ld	de,Buffers.input_line.Symbols_Num	; куда
;	ld	a,(hl)			; скопир. строку (с нулем)
;	ldi
;	or	a
;	jr	nz,$-4
	; уст. историю на посл. пустую строку
	ld	a,(history_count)	; число строк в истории
	ld	(history_cur_string),a	; номер тек. строки истории
	ret


; Событие - обычная клавиша
EvComKeys:
	ld	a,(hl)				;+1 what
	cp	#1B				; Esc
	jp	z,clear_input_line		; очистить строку ввода
	cp	#0D				; Enter
	jr	z,Enter
	cp	8				; Backspace
	jr	z,inpline_work
	cp	" "
	ret	c
inpline_work:
	ld	de,input_line_done
	push	de
	ld	hl,Buffers.input_line	; структура буфера ~input line~
	ex	af,af'
	res	7,(iy + Input_Line.ReadyString)	;+1 флаг ReadyString
	ld	a,(insert_mode)			; режим ввода: 1-inser, 0-overwrite
	and	1
	rrca					; вправо (мл.бит -> перенос)
	or	(iy + Input_Line.ReadyString)
	ld	(iy + Input_Line.ReadyString),a	;+1 флаг ReadyString
	ex	af,af'
	cp	8				; Backspace
	jp	z,back_space
	ex	af,af'
	ld	a,(iy + Input_Line.Symbols_Num)	; InputSymb
	cp	(iy + Input_Line.max_Len)
	jr	nz,ILn___
	ld	a,(iy + Input_Line.Cur_X)
	add	a,(iy + Input_Line.Left_Shift)
	cp	(iy + Input_Line.max_Len)
	;ret	nc
	JR	NC,LastChar_BEEP
	bit	7,(iy + Input_Line.ReadyString)
	;ret	nz
	JR	NZ,NoMoreChars_BEEP
ILn___:	ld	a,(iy + Input_Line.Symbols_Num)
	sub	(iy + Input_Line.Left_Shift)
	sub	(iy + Input_Line.Cur_X)
	jr	z,no_insert
	dec	(iy + Input_Line.Symbols_Num)
	bit	7,(iy + Input_Line.ReadyString)
	jr	z,no_insert
	inc	(iy + Input_Line.Symbols_Num)
	; ввод в середину текста (вставка)
	ld	c,a
	ld	b,0
	ld	hl,Buffers.input_line	; структура буфера ~input line~
	ld	a,(iy + Input_Line.Symbols_Num)	;+4 число введ. символов
	add	a,l
	ld	l,a
	jr	nc,$+3				;!FIXIT
	inc	h
	inc	hl
	inc	hl
	inc	hl
	inc	hl
	inc	hl
	ld	d,h
	ld	e,l
	dec	hl
	lddr
no_insert:
	ld	hl,Buffers.input_line	; структура буфера ~input line~
	ld	a,(iy + Input_Line.Cur_X)	; X тек. полож. курсора в строке
	add	a,(iy + Input_Line.Left_Shift)
	add	a,l
	ld	l,a
	jr	nc,$+3				;!FIXIT
	inc	h
	inc	hl
	inc	hl
	inc	hl
	inc	hl
	inc	hl
	ex	af,af'
	ld	(hl),a				; сохр. символ в строке
	inc	(iy + Input_Line.Symbols_Num)
	inc	(iy + Input_Line.Cur_X)
	ld	a,(width_inpline)		; ширина поля ввода
	cp	(iy + Input_Line.Cur_X)		; X тек. полож. курсора в пределах строки
	jr	nz,$+8				;!FIXIT
	; курсор за полем
	inc	(iy + Input_Line.Left_Shift)	; смещ. строки за левый край
	dec	(iy + Input_Line.Cur_X)		; X тек. полож. курсора в пределах строки
	call	print_inpline			; вывести строку на экран
	pop	de				; восст. баланс стека
input_line_done:
	ret
LastChar_BEEP:
	;!TODO если символы привысили максимальное число, то на экране
	;      в строке остаётся эхо нажатой клавиши, которая не влезла 
	;      и висит до нажатия очередной клавиши. Исправить.
	LD	A,7 	;ASCII BELL
	LD	C,Dss.PutChar
	JP	ToDSS

NoMoreChars_BEEP:
	;!TODO если символы привысили максимальное число, то на экране
	;      в строке остаётся эхо нажатой клавиши, которая не влезла 
	;      и висит до нажатия очередной клавиши. Исправить.
	LD	A,7 	;ASCII BELL
	LD	C,Dss.PutChar
	JP	ToDSS

; Событие - курс. клавиши или комбинации
EvComComb:
	ld	b,(hl)				;+1 what
	inc	hl
	ld	a,(hl)				;+2 what
	ld	hl,Buffers.input_line	; структура буфера ~input line~
	ld	de,input_line_done		; точка выхода
	push	de
	cp	#54				; курсор влево
	jr	z,Left
	cp	#56				; курсор вправо
	jr	z,Right
	cp	#58				; курсор вверх, пред. строка истории
	jp	z,history_prev
	cp	#52				; курсор вниз, след. строка истории
	jp	z,history_next
	cp	#59				; PageUp, в начало истории
	jp	z,history_begin
	cp	#53				; PageDown, в конец истории
	jp	z,history_last
	cp	#4F				; Del, удалить символ в тек. позиции
	jp	z,Delete
	cp	#57				; Home, в начало строки
	jp	z,Home
	cp	#51				; End, в конец строки
	jp	z,End1
	cp	#50				; Ins, смена режима ввода
	jr	z,change_insert_mode
	bit	5,b				; Ctrl бит
	jr	z,.exit
	cp	#4F+#80				; Ctrl+Del, очистить историю команд
	jp	z,clear_history
.exit:	pop	de
	ret

; Смена режима ввода
change_insert_mode:
	ld	a,(insert_mode)
	xor	1
	ld	(insert_mode),a
	ret

; Курсор влево
Left:	ld	a,(iy + Input_Line.Cur_X)
	dec	a
	jp	p,ComPrint
	ld	a,(iy + Input_Line.Left_Shift)	; смещ. строки за левый край
	sub	step_scroll			; шаг скроллинга
	ret	c				; курсор в крайнем левом полож.
	ld	(iy + Input_Line.Left_Shift),a	; X смещ. строки за левый край (в символах)
	ld	a,(iy + Input_Line.Cur_X)	; X полож. курсора в пределах строки
	add	a,step_scroll-1			; шаг скроллинга
ComPrint:
	ld	(iy + Input_Line.Cur_X),a
	jp	print_inpline			; вывести строку на экран

; Курсор вправо
Right:	ld	a,(iy + Input_Line.Cur_X)	; X полож. курсора в пределах строки
	add	a,(iy + Input_Line.Left_Shift)	; смещ. строки за левый край
	cp	(iy+4)				; число введ. символов
	ret	z
	ld	a,(width_inpline)		; ширина поля ввода
	ld	b,a
	ld	a,(iy + Input_Line.Cur_X)	; X полож. курсора в пределах строки
	inc	a
	cp	b
	jr	nz,ComPrint
	inc	(iy + Input_Line.Left_Shift)	; смещ. строки за левый край
	ld	a,(iy + Input_Line.Cur_X)	; X полож. курсора в пределах строки
	sub	step_scroll-1			; шаг скроллинга
	jr	ComPrint

; Backspace - удалить символ левее курсора
back_space:
	ld	a,(iy + Input_Line.Cur_X)	; X тек. полож. курсора в строке
	or	a
	jr	nz,back_space1
	ld	a,(iy + Input_Line.Left_Shift)	; смещ. строки за левый край
	sub	step_scroll			; шаг скроллинга
	ret	c
	ld	(iy + Input_Line.Left_Shift),a
	inc	(iy + Input_Line.Cur_X)		;+2 тек. полож. курсора в строке
back_space1:
	ld	hl,Buffers.input_line	; структура буфера ~input line~
	ld	a,(iy + Input_Line.Cur_X)	;+2 X тек. полож. курсора в строке
	add	a,(iy + Input_Line.Left_Shift)	;+3 смещ. строки за левый край
	add	a,l
	ld	l,a
	jr	nc,$+3				;!FIXIT
	inc	h
	inc	hl
	inc	hl
	inc	hl
	inc	hl
	inc	hl
	ld	d,h
	ld	e,l
	dec	de
	ld	a,(iy + Input_Line.Symbols_Num)	;+4 число введ. символов
	sub	(iy + Input_Line.Left_Shift)	; смещ. строки за левый край
	sub	(iy + Input_Line.Cur_X)		; X полож. курсора в пределах строки
	jr	z,$+7				; курсор за концом строки ;!FIXIT
	ld	c,a
	ld	b,0
	ldir					; обновить остаток строки
	xor	a
	ld	(de),a				; в конец строки
	dec	(iy + Input_Line.Cur_X)		; X полож. курсора в пределах строки
	dec	(iy + Input_Line.Symbols_Num)	; число введ. символов
	jp	print_inpline			; вывести строку на экран

; Delete - удалить символ в тек. позиции
Delete:	ld	hl,Buffers.input_line	; структура буфера ~input line~
	ld	a,(iy + Input_Line.Cur_X)	; X тек. полож. курсора в строке
	inc	a
	add	a,(iy + Input_Line.Left_Shift)	; смещ. строки за левый край
	add	a,l
	ld	l,a
	jr	nc,$+3				;!FIXIT
	inc	h
	inc	hl
	inc	hl
	inc	hl
	inc	hl
	inc	hl
	ld	d,h
	ld	e,l
	dec	de
	ld	a,(iy + Input_Line.Symbols_Num)	;+4 число введ. символов
	sub	(iy + Input_Line.Left_Shift)	; смещ. строки за левый край
	sub	(iy + Input_Line.Cur_X)		; X тек. полож. курсора в строке
	ret	z				; курсор за концом строки
	ld	c,a
	ld	b,0
	ldir					; обновить остаток строки
	xor	a
	ld	(de),a				; в конец строки
	dec	(iy + Input_Line.Symbols_Num)	; число введ. символов
	jp	print_inpline			; вывести строку на экран

; Home - в начало строки
Home:	ld	a,(iy + Input_Line.Cur_X)	; X тек. полож. курсора в строке
	add	a,(iy + Input_Line.Left_Shift)	; смещ. строки за левый край
	ret	z
	xor	a				; X полож. курсора
	ld	(iy + Input_Line.Cur_X),a	; X полож. курсора в пределах строки
	ld	(iy + Input_Line.Left_Shift),a	; смещ. строки за левый край
	jp	ComPrint			; вывести строку на экран

; End - в конец строки
End1:	ld	a,(iy + Input_Line.Symbols_Num)	;+4 число введ. символов
	sub	(iy + Input_Line.Left_Shift)	;+3 смещ. строки за левый край
	cp	(iy + Input_Line.Cur_X)		;+2 X тек. полож. курсора в строке
	ret	z
	add	a,(iy + Input_Line.Left_Shift)	; смещ. строки за левый край
	ld	c,a
	ld	(iy + Input_Line.Left_Shift),0	; смещ. строки за левый край
	ld	a,(width_inpline)		; ширина поля ввода
	sub	c
	jr	z,EndLp
	jr	nc,EndNIL
	neg
EndLp:	inc	(iy + Input_Line.Left_Shift)	; X смещ. строки за левый край
	sub	step_scroll			; шаг скроллинга
	jr	nc,EndLp
EndNIL:	ld	a,(iy + Input_Line.Symbols_Num)	; число введ. символов
	sub	(iy + Input_Line.Left_Shift)	; смещ. строки за левый край
	jp	ComPrint			; вывести строку на экран




; Очистить буфер строки
clear_input_line:
	call	clear_inpline			; очистить структуру ~input line~
	jp	print_inpline			; вывести строку на экран


; очистить структуру ~input line~
clear_inpline:
	xor	a
	ld	hl,Buffers.input_line	; структура буфера ~input line~
	ld	b,(hl)				;+0 макс. длина строки
	inc	hl	
	ld	(hl),a				;+1 сбр. флаг ReadyString
	inc	hl	
	ld	(hl),a				;+2 X тек. полож. курсора в строке
	inc	hl	
	ld	(hl),a				;+3 смещ. строки за левый край
	inc	hl	
	ld	(hl),a				;+4 число введ. символов
	cp	b	
	ret	z	
	inc	hl				;+5 буфер редакт. строки
	ld	(hl),a	
	djnz	$-2				;!FIXIT
	ret



; Вставить строку из history-буфера
; вход: de=структура строки: +0=длина строки, +1=строка
put_from_history:
	call	clear_inpline			; очистить строку ввода
	ld	a,(de)				;+0 длина строки
	ld	c,a
put_history_loop:
	inc	de
	ld	hl,Buffers.input_line	; структура буфера ~input line~
	ld	a,(iy + Input_Line.Cur_X)	; X тек. полож. курсора в строке
	add	a,(iy + Input_Line.Left_Shift)
	add	a,l
	ld	l,a
	jr	nc,$+3				;!FIXIT
	inc	h
	inc	hl
	inc	hl
	inc	hl
	inc	hl
	inc	hl
	ld	a,(de)
	ld	(hl),a
	inc	(iy + Input_Line.Symbols_Num)	; число введ. символов
	inc	(iy + Input_Line.Cur_X)		; X тек. полож. курсора в строке
	ld	a,(width_inpline)		; ширина поля ввода
	cp	(iy + Input_Line.Cur_X)		; X тек. полож. курсора в пределах строки
	jr	nz,$+8				;!FIXIT
	; курсор за правым краем поля ввода
	inc	(iy + Input_Line.Left_Shift)	; смещ. строки за левый край
	dec	(iy + Input_Line.Cur_X)		; X тек. полож. курсора в пределах строки
	dec	c
	jr	nz,put_history_loop
	; вывести строку на экран
	jp	print_inpline



; Очистить историю команд
clear_history:
	call	clear_input_line		; очистить строку ~input line~
	xor	a
	ld	(history_count),a		; число строк в history
	ld	(history_cur_string),a		; номер тек. строки history
	ld	hl,Buffers.history		; конец посл. строки
	ld	(history_end),hl
	ret






;========================================================================
;                      History Код
;========================================================================

history_count:
	db	0				; число строк в истории
	;
history_cur_string:
	db	0				; номер тек. строки истории
	;
history_end:
	dw	Buffers.history			; конец послед. строки истории



;-------------------------------------------------
; В начало истории
;-------------------------------------------------
history_begin:
	ld	a,(history_count)
	or	a
	ret	z				; нет строк
	xor	a
	ld	(history_cur_string),a
	jr	history_copy			; перейти на 1-ю строку

;-------------------------------------------------
; В конец истории
;-------------------------------------------------
history_last:
	ld	a,(history_count)
	or	a
	ret	z				; нет строк
	ld	(history_cur_string),a		; уст. послед. пустую строку
	jp	clear_input_line		; вернуть пустую строку

;-------------------------------------------------
; Следующая строка
;-------------------------------------------------
history_next:
	ld	a,(history_count)
	or	a
	ret	z			; нет строк
	dec	a
	ld	b,a
	ld	hl,history_cur_string
	ld	a,(hl)
	cp	b
	jr	c,$+7			;!FIXIT
	inc	b
	ld	(hl),b
	jp	clear_input_line	; вернуть пустую строку
	;
	inc	a
	ld	(hl),a
	jr	history_copy

;-------------------------------------------------
; Предыдущая строка
;-------------------------------------------------
history_prev:
	ld	a,(history_count)
	or	a
	ret	z			; нет строк
	ld	b,a
	ld	hl,history_cur_string
	ld	a,(hl)
	or	a
	jr	z,history_copy		; уперлись в начало истории
	cp	b
	jr	c,$+3			;!FIXIT
	ld	a,b
	dec	a
	ld	(hl),a
; перейти на строку по ее индексу
history_copy:
	call	history_index
	jp	put_from_history	; строку из history в буфер ком-строки

; вход: а=индекс строки
; выход: de=строка (ее структура из history-буфера)
history_index:
	ld	b,0
	ld	hl,Buffers.history	; буфер истории
	or	a			; индекс строки
	jr	z,hist_index		; 1-я строка истории
	ld	c,(hl)			; размер строки
	inc	c
	add	hl,bc			; на след. строку
	dec	a
	jr	nz,$-4			;!FIXIT
hist_index:
	ex	de,hl
	ret


;-----------------------------------------------------------
; Добавить новую строку в конец буфера истории.
; Если строка не влезает, удаляются самые старые строки до
; тех пор, пока появится достаточно места для новой строки.
;-----------------------------------------------------------
history_adding:
	ld	de,Buffers.input_line.Symbols_Num	; структура строки
	call	history_compare				; сравнить строки
	ret	z					; уже есть такая строка
	ld	bc,(history_end)			; адрес конца посл. строки
	ld	hl,Buffers.history + history_size 	; адрес конца буфера
	and	a
	sbc	hl,bc					; hl=размер своб. места
	ld	a,(de)					; длина новой строки
	inc	a
	ld	c,a
	xor	a
	ld	b,a
	sbc	hl,bc					; умещ. в своб. месте буфера истории ?
	jr	nc,history_add_ok			; да
	; удалить первую (самую старую) строку из буфера
	;push	de
	ld	de,Buffers.history			; буфер истории
	ld	a,(de)					; длина 1-й строки
	inc	a
	ld	c,a
	xor	a
	ld	b,a
	ld	hl,(history_end)
	sbc	hl,bc
	ld	(history_end),hl	; конец посл. строки
	ld	l,e			; hl=history_buff
	ld	h,d
	add	hl,bc			; начало 2-й строки
	push	hl
	ld	hl,history_size		; размер буфера
	and	a
	sbc	hl,bc
	ld	c,l			; размер остатка буфера
	ld	b,h
	pop	hl			; начало 2-й строки
	ldir
	ld	hl,history_count
	dec	(hl)			; --число строк в history
	;pop	de			; восст. адрес Buffers.input_line.Symbols_Num
	jr	history_adding
	;
history_add_ok:
	ld	hl,(history_end)	; адрес конца посл. строки
	ex	de,hl
	ldir
	ld	(history_end),de	; конец посл. строки
	ld	hl,history_count
	ld	a,(hl)
	ld	(history_cur_string),a	; тек. строка history
	inc	(hl)			; ++число строк в history
	ret


; Сравнить строки. Если строки равны, то переместить
; тек. строку в конец истории.
; вход: de=структура строки: +0=длина строки, +1=строка
; выход: Z-есть строка
;        NZ-нет строки
history_compare:
	ld	hl,history_count
	ld	b,(hl)			; число строк в history
	dec	b
	inc	b
	jr	z,hist_comp_quit	; history-буфер пустой
	ex	af,af'
	xor	a			; сбр. индекс сравн. строки
	ex	af,af'
	ld	hl,Buffers.history	; буфер истории
history_comp_loop:
	push	de
	ld	(move_cur_str+1),hl	; тек. строка истории
	ld	c,(hl)			; длина тек. строки history
	ld	a,(de)			; длина новой строки
	inc	hl
	inc	de
	cp	c
	jr	z,hist_comp_loop	; строки одинаковой длины
	ld	a,l
	add	a,c
	ld	l,a
	ld	a,h
	adc	a,0
	ld	h,a
	jr	hist_comp_next
	;
; сравнить строки
hist_comp_loop:
	ld	a,(de)
	cp	(hl)
	jr	nz,hist_comp_notequal	; строки не равны
	inc	hl
	inc	de
	dec	c
	jr	nz,hist_comp_loop
	; строки равны
	jr	move_to_end_history	; найденную строку в конец истории
	;
hist_comp_notequal:
	inc	hl
	dec	c
	jr	nz,$-2			; до конца строки		;!FIXIT $
hist_comp_next:
	pop	de
	ex	af,af'
	inc	a			; ++индекс сравн. строки
	ex	af,af'
	djnz	history_comp_loop
hist_comp_quit:
	xor	a
	dec	a			; NZ-флаг
	ret

; переместить тек. строку в конец истории
move_to_end_history:
	ld	a,(history_count)	; число строк истории
	ld	c,a
	dec	c
	ex	af,af'			; индекс найденной строки
	cp	c
	jr	nc,not_move_to_end	; найденная строка уже в конце
	; сохр. строку во врем. буфере
move_cur_str:
	ld	hl,0			; тек. строка истории
	ld	de,Buffers.work.buffer		; врем. буфер
	ld	c,(hl)			;+0 длина строки
	inc	c			; учесть ячейку длины строки
	xor	a
	ld	b,a
	push	bc
	push	hl
	ldir
	pop	de			; куда (на место старой строки)
	pop	bc
	; сдвинуть остаток буфера на место сохр. строки
	push	hl
	ld	hl,(history_end)	; конец посл. строки истории
	and	a
	sbc	hl,de
	and	a
	sbc	hl,bc
	ld	c,l			; величина сдвига
	ld	b,h
	pop	hl			; откуда
	ldir
	; восст. строку из врем. буфера в конец истории
	ld	hl,Buffers.work.buffer		; врем. буфер
	ld	c,(hl)
	inc	c
	ld	b,a
	ldir
not_move_to_end:
	ld	a,(history_count)
	dec	a
	ld	(history_cur_string),a	; тек. строка history
	pop	de
	xor	a			; Z флаг
	ret





;!FIXIT к буферам почти всё
////////////////////////////////////////////////////////////////////////
; 1	0
;cursor_position:
;	dw	0			; Y/X полож. курсора

; 2	0
width_inpline:
.MAX	EQU	80
	db	width_inpline.MAX-4	; тек. ширина поля ввода

; 3	0
YXpos:	dw	0			; Y/X начало ком-строки

; 4	0
; режим ввода
insert_mode:
	db	1			; 01/00 inser/overwrite

; 5	0
; экранный путь
; screen_path:
; 	db	"A:"
; 	BLOCK	max_screen_path+1,0	; 32+1

; 6	0
; системный путь
; system_path:
; 	BLOCK	256,0	;!HARDCODE

; ; 7	0
; ; Структура строки ввода ~input line~
; Buffers.input_line.:
; 	db	max_len_comline		;+0 254 макс. число ввод. символов
; 	db	0			;+1 флаг ReadyString
; 	db	0			;+2 X тек. полож. курсора в пределах строки
; 	db	0			;+3 X смещ. строки за левый край (в символах)
; 	db	0			;+4 число введенных символов
; 	BLOCK	max_len_comline+1,0	;+5 строка ввода

; ; 8	0
; ; Буфер истории
; history_buff:
; 	BLOCK	history_size,0		; 256

; ; 9	0
; ; Рабочий буфер
; Buffers.work.buffer:
; 	BLOCK	512,0
////////////////////////////////////////////////////////////////////////
;