	include	ed.inc

	.code

prX		equ	1
prFirstX	equ	2
prSecondX	equ	4

Insert1X	proc	near
	mov	ds:Perverted,0
	cmp	ds:CursorPos.X,1
	jbe	@@1
	mov	byte ptr ds:CParam,'x'
	Invoke	InsertNoOver
	Invoke	SetEditDS
	jc	@@1
	mov	byte ptr ds:CParam,0dh
	Invoke	InsertNoOver
	Invoke	SetEditDS
	jc	@@1
	mov	ds:Perverted,prX
	Invoke	SetTempPos
	Invoke	SetEditDS
	clc
@@1:	ret
Insert1X	endp

Insert2Xs	proc	near
	Invoke	MoveToBlockBegRaw
	Invoke	SetEditDS
	cmp	ds:CursorPos.X,1
	jbe	@@1
	mov	byte ptr ds:CParam,'x'
	Invoke	InsertNoOver
	Invoke	SetEditDS
	jc	@@2
	mov	byte ptr ds:CParam,0dh
	Invoke	InsertNoOver
	Invoke	SetEditDS
	jc	@@3
	or	ds:Perverted,prFirstX
	Invoke	SetBlockBegRaw
@@1:	Invoke	MoveToBlockEndRaw
	Invoke	SetEditDS
	cmp	ds:CursorPos.X,1
	jbe	@@3
	mov	byte ptr ds:CParam,'x'
	Invoke	InsertNoOver
	Invoke	SetEditDS
@@2:	jc	@@3
	mov	byte ptr ds:CParam,0dh
	Invoke	InsertNoOver
	Invoke	SetEditDS
	jc	@@3
	or	ds:Perverted,prSecondX
	Invoke	SetBlockEndRaw
	Invoke	SetEditDS
	clc
@@3:	ret
Insert2Xs	endp

DeleteXs	proc	near
	test	ds:Perverted,prSecondX
	jz	@@1
	Invoke	MoveToBlockEndRaw
	Invoke	FoolBS
	Invoke	FoolBS
	Invoke	SetEditDS
@@1:	test	ds:Perverted,prFirstX
	jz	@@2
	Invoke	MoveToBlockBegRaw
	Invoke	FoolBS
	Invoke	FoolBS
@@2:	Invoke	MoveToTempPos
	Invoke	SetEditDS
	test	ds:Perverted,prX
	jz	@@3
	Invoke	FoolBS
	Invoke	FoolBS
	Invoke	SetEditDS
@@3:	mov	ds:Perverted,0
	ret
DeleteXs	endp

	Entry	DeleteBlockRaw
	Invoke	BlockShown
	Invoke	SetEditDS
	jnz	@@2
@@1:	jmp	@@8
@@2:	push	ds:Options
	or	ds:Options,eoUndoDisabled
	mov	ds:Perverted,0
	call	Insert2Xs
	jc	@@1
	push	ds:BlockBeg.Y ds:BlockEnd.Y ds:CursorPos.Y
	Invoke	ShiftDeleteBlock
	Invoke	SetEditDS
	pop	ds:CursorPos.Y ds:BlockEnd.Y ds:BlockBeg.Y
	Invoke	MoveToBlockBegRaw
	Invoke	SetEditDS
	mov	bx,ds:CurPage
	mov	ax,ds:CPFirstLine
	add	ax,[bx].LinesInPage
	cmp	ax,ds:BlockEnd.Y
	jbe	@@3
	jmp	@@6
@@3:	Invoke	GoCurPos
	Invoke	UseCurPage
	mov	ax,ds:CursorPos.Y
	cmp	ax,ds:CPFirstLine
	je	@@4
	mov	bx,di
	mov	si,ds:CurPage
	mov	[si].PageLength,bx
	mov	es:CurLineNum,-1
	mov	cx,ax
	sub	ax,ds:CPFirstLine
	xchg	ax,[si].LinesInPage
	sub	ax,[si].LinesInPage
	sub	ds:BlockEnd.Y,ax
	add	si,size PageInfo
	mov	ds:CurPage,si
	mov	ds:CPFirstLine,cx
@@4:	mov	ax,ds:BlockEnd.Y
	mov	bx,ds:CurPage
	sub	ax,[bx].LinesInPage
	jb	@@5
	cmp	ax,ds:BlockBeg.Y
	jb	@@5
	mov	ds:BlockEnd.Y,ax
	Invoke	DeletePage
	Invoke	SetEditDS
	jmp	@@4
@@5:	mov	ax,ds:CPFirstLine
	mov	ds:CursorPos.Y,ax
	mov	ds:CursorPos.X,1
@@6:	push	ds:CursorPos.Y
	Invoke	GoCurPos
	mov	ax,bx
	sub	ax,di
	sub	ax,size LineHeader-1
	push	ax
	push	di bx
	Invoke	MoveToBlockEndRaw
	Invoke	GoCurPos
	Invoke	UseCurPage
	mov	cx,es:[di].LineLength
	mov	ax,ds:BlockEnd.X
	dec	ax
	sub	cx,ax
	mov	si,bx
	pop	di bx
	lea	ax,[bx+size LineHeader]
	mov	dx,di
	sub	dx,ax
	add	dx,cx
	mov	es:[bx].LineLength,dx
	push	ds
	push	es
	pop	ds
	cld
	rep	movsb
	pop	ds
	inc	di
	and	di,0fffeh
	inc	si
	and	si,0fffeh
	mov	bx,ds:CurPage
	mov	cx,[bx].PageLength
	sub	cx,si
	push	ds
	push	es
	pop	ds
	cld
	rep	movsb
	pop	ds
	mov	[bx].PageLength,di
	mov	ax,ds:BlockEnd.Y
	pop	dx
	pop	cx
	sub	ax,cx
	sub	[bx].LinesInPage,ax
	mov	es:CurLineNum,-1
	mov	ds:BlockEnd.X,dx
	mov	ds:BlockEnd.Y,cx
	test	ds:Perverted,prFirstX
	jz	@@7
	Invoke	MoveToBlockBegRaw
	Invoke	FoolBS
	Invoke	FoolBS
@@7:	Invoke	MoveToBlockBegRaw
	Invoke	SetEditDS
	pop	ds:Options
	or	ds:Modified,emShow+emUpdate
	or	ds:RedrawFlags,rfFullScreen+rfPageChanged
	Invoke	InvalidateUndo
@@8:	Exit	DeleteBlockRaw

	Entry	ReserveSpace
	Invoke	FindCurLine
	jc	@@1
	cmp	bx,size PageHeader
	je	@@1
	Invoke	RestToNextPage
	jnc	@@1
	Invoke	InsertPage
	jc	@@1
	Invoke	RestToNextPage
	jnc	@@1
@@1:	Exit	ReserveSpace

Prepare	proc	near
	Invoke	SetEditDS
	mov	ax,ds:TempPos.Y
	cmp	ax,ds:BlockBeg.Y
	jae	@@1
	Invoke	MoveToTempPos
	Invoke	ReserveSpace
	jc	@@2
@@1:	Invoke	MoveToBlockBegRaw
	Invoke	ReserveSpace
	jc	@@2
	Invoke	MoveToBlockEndRaw
	Invoke	ReserveSpace
	jc	@@2
	Invoke	MoveToTempPos
	Invoke	ReserveSpace
@@2:	Invoke	SetEditDS
	ret
Prepare	endp

	Loc	PInfo,byte,<size PageInfo>
	Loc	Distance,word,1
	Loc	CurrentPage,word,1
	Loc	FirstPage,word,1
	Loc	FinPage,word,1
	Loc	TargetPage,word,1
	Loc	CyclingPage,word,1

_MoveBlock	proc	near
	Invoke	SetEditDS
	mov	ax,ds:BlockBeg.Y
	Invoke	FindPage
	Invoke	SetEditDS
	jc	@@1
	mov	FirstPage,bx
	jcxz	@@2
@@1:	jmp	@@13
@@2:	mov	ax,ds:BlockEnd.Y
	Invoke	FindPage
	Invoke	SetEditDS
	jc	@@1
	test	cx,cx
	jz	@@3
	add	bx,size PageInfo
@@3:	mov	FinPage,bx
	mov	TargetPage,bx
	cmp	bx,FirstPage
	jbe	@@1
	mov	ax,ds:TempPos.Y
	Invoke	FindPage
	Invoke	SetEditDS
	jc	@@1
	test	cx,cx
	jz	@@4
	add	bx,size PageInfo
@@4:	cmp	bx,FinPage
	ja	@@5
	mov	ax,FirstPage
	mov	FinPage,ax
	mov	FirstPage,bx
	cmp	bx,ax
	jb	@@6
@@5:	mov	TargetPage,bx
	cmp	bx,FinPage
	jbe	@@1
@@6:	push	ds
	pop	es
	cld
	mov	ax,FirstPage
	add	ax,TargetPage
	sub	ax,FinPage
	mov	FinPage,ax
	mov	ax,TargetPage
	sub	ax,FirstPage
	mov	Distance,ax
	mov	ax,FirstPage
	mov	CurrentPage,ax
	mov	CyclingPage,ax
	jmp	@@11
@@7:	sub	Distance,size PageInfo
	jb	@@13
	mov	si,CyclingPage
	mov	di,si
	cmp	di,FinPage
	jae	@@8
	add	si,TargetPage
	jmp	@@9
@@8:	add	si,FirstPage
@@9:	sub	si,FinPage
	mov	cx,size PageInfo shr 1
	cmp	si,CurrentPage
	je	@@10
	mov	CyclingPage,si
	rep	movsw
	jmp	@@7
@@10:	SetTurboDS
	lea	si,PInfo
	rep	movsw
	push	es
	pop	ds
	cmp	Distance,0
	je	@@12
	mov	ax,CurrentPage
	add	ax,size PageInfo
	mov	CurrentPage,ax
	mov	CyclingPage,ax
@@11:	mov	si,ax
	lea	di,PInfo
	mov	ax,_Data
	mov	es,ax
	mov	cx,size PageInfo shr 1
	rep	movsw
	mov	ax,ds
	mov	es,ax
	jmp	@@7
@@12:	ret
@@13:	jmp	@@12
_MoveBlock	endp

CheckSpace	proc	near
	Invoke	TotalLines
	Invoke	SetEditDS
	push	ax
	sub	cx,cx
	mov	ax,1
	cmp	ax,ds:CursorPos.X
	adc	cx,0
	cmp	ax,ds:BlockBeg.X
	adc	cx,0
	cmp	ax,ds:BlockEnd.X
	adc	cx,0
	mov	ax,cx
	mov	cx,32767
	sub	cx,ax
	pop	ax
	cmp	cx,ax
	ret
CheckSpace	endp

	Entry	MoveBlockRaw
	Invoke	BlockShown
	Invoke	SetEditDS
	jnz	@@1
	jmp	@@16
@@1:	call	CheckSpace
	jnc	@@2
	mov	ax,erTooManyLines
	or	ds:Errors,al
	mov	ds:ReturnCode,ax
	jmp	@@16
@@2:	mov	ax,ds:ScreenPos.Y
	cmp	ax,ds:BlockBeg.Y
	jbe	@@4
	mov	bx,ds:BlockEnd.Y
	cmp	ax,bx
	ja	@@3
	mov	bx,ax
@@3:	sub	bx,ds:BlockBeg.Y
	sub	ax,bx
	jnz	@@4
	inc	ax
@@4:	push	ax ds:Options
	or	ds:Options,eoUndoDisabled
	and	ds:Options,not eoOverwrite
	Invoke	SetTempPos
	Invoke	SetEditDS
	mov	ax,ds:TempPos.Y
	mov	bx,ds:TempPos.X
	cmp	ax,ds:BlockBeg.Y
	jb	@@6
	jne	@@5
	cmp	bx,ds:BlockBeg.X
	jb	@@6
@@5:	cmp	ax,ds:BlockEnd.Y
	ja	@@6
	jb	@@11
	cmp	bx,ds:BlockEnd.X
	jbe	@@11
@@6:	or	ds:Modified,emShow+emUpdate
	or	ds:RedrawFlags,rfFullScreen+rfPageChanged
	mov	ax,ds:TempPos.Y
	Invoke	FindPage
	Invoke	UseCurPage
	jc	@@7
	Invoke	StoreLinesInfo
@@7:	mov	ax,ds:BlockBeg.Y
	mov	cx,ds:BlockEnd.Y
	sub	cx,ax
	inc	cx
@@8:	push	ax cx
	Invoke	FindPage
	Invoke	UseCurPage
	jc	@@9
	Invoke	StoreLinesInfo
	pop	cx ax
	inc	ax
	loop	@@8
@@9:	call	Insert1X
	jc	@@10
	call	Insert2Xs
	jnc	@@12
@@10:	call	DeleteXs
	Invoke	FoolBS
	Invoke	SetEditDS
@@11:	stc
	jmp	@@15
@@12:	call	Prepare
	jnc	@@13
	Invoke	CompactPages
	call	Prepare
	jc	@@10
@@13:	call	_MoveBlock
	Invoke	GoTopPage
	Invoke	ShiftMoveBlock
	push	ax
	Invoke	MoveToBlockEndRaw
	Invoke	SetEditDS
	pop	ax
	add	ax,ds:BlockBeg.Y
	mov	ds:BlockEnd.Y,ax
	test	ds:Perverted,prFirstX
	jz	@@14
	Invoke	FoolBS
	Invoke	FoolBS
	Invoke	SetEditDS
	and	ds:Perverted,not prFirstX
@@14:	mov	ax,ds:BlockBeg.Y
	mov	ds:TempPos.Y,ax
	call	DeleteXs
	Invoke	InvalidateUndo
	Invoke	SetEditDS
	clc
@@15:	pop	ds:Options ds:ScreenPos.Y
	lahf
	or	ds:RedrawFlags,rfFullScreen+rfPageChanged
	sahf
@@16:	Exit	MoveBlockRaw

	Loc	SaveBlockBegX,word,1
	Loc	SaveBlockBegY,word,1
	Loc	SaveBlockEndX,word,1
	Loc	SaveBlockEndY,word,1
	Loc	SaveCursorPosX,word,1
	Loc	SaveCursorPosY,word,1
	Loc	CurY,word,1
	Loc	OffsetX,word,1
	Loc	EndX,word,1
	Loc	TempBufY,word,1
	Loc	Len,word,1
	Loc	ErrorOccured,word,1
	Entry	CopyBlockRaw
	Invoke	BlockShown
	jnz	@@1
	jmp	@@13
@@1:	call	CheckSpace
	jc	@@2
	mov	cx,ax
	mov	ax,ds:BlockEnd.Y
	sub	ax,ds:BlockBeg.Y
	inc	ax
	jz	@@2
	add	ax,cx
	jc	@@2
	cmp	ax,32767
	jb	@@3
@@2:	mov	ax,erTooManyLines
	or	ds:Errors,al
	mov	ds:ReturnCode,ax
	jmp	@@13
@@3:	inc	cx
	mov	TempBufY,cx
	Invoke	FindCurLine
	Invoke	UseCurPage
	mov	bx,ds:CurPage
	Invoke	StoreLinesInfo
	Invoke	UpdateUndo
	Invoke	SetEditDS
	push	ds:Options
	or	ds:Options,eoUndoDisabled
	and	ds:Options,not eoOverwrite
	mov	ax,ds:BlockBeg.Y
	mov	SaveBlockBegY,ax
	mov	CurY,ax
	mov	ax,ds:BlockBeg.X
	mov	SaveBlockBegX,ax
	dec	ax
	mov	OffsetX,ax
	mov	ax,ds:BlockEnd.X
	mov	SaveBlockEndX,ax
	dec	ax
	mov	EndX,ax
	mov	ax,ds:BlockEnd.Y
	mov	SaveBlockEndY,ax
	mov	ax,ds:CursorPos.X
	mov	SaveCursorPosX,ax
	mov	ax,ds:CursorPos.Y
	mov	SaveCursorPosY,ax
	mov	ErrorOccured,0
@@4:	Invoke	InsertPageToEnd
	Invoke	SetEditDS
	jnc	@@5
	jmp	@@9
@@5:	Invoke	LockPage
@@6:	mov	ax,CurY
	Invoke	FindLine
	Invoke	UseCurPage
	jc	@@9
	cmp	bx,dx
	jae	@@9
	mov	si,bx
	mov	ax,CurY
	cmp	ax,ds:BlockEnd.Y
	mov	ax,es:[si].LineLength
	jne	@@7
	mov	ax,EndX
@@7:	sub	ax,OffsetX
	jae	@@8
	sub	ax,ax
@@8:	mov	Len,ax
	add	ax,size LineHeader
	mov	bx,ds:LastPage
	mov	di,[bx-size PageInfo].PageLength
	add	ax,di
	inc	ax
	and	al,0feh
	cmp	ax,ds:PageSize
	ja	@@4
	mov	[bx-size PageInfo].PageLength,ax
	inc	[bx-size PageInfo].LinesInPage
	push	ds
	push	es
	les	bx,ds:LockedPage
	mov	es,es:[bx]
	pop	ds
	cld
	mov	cx,Len
	mov	es:[di].LineLength,cx
	mov	es:[di].LineNumber,0
	mov	ax,size LineHeader
	add	di,ax
	add	ax,OffsetX
	mov	OffsetX,0
	add	si,ax
	shr	cx,1
	rep	movsw
	rcl	cx,1
	rep	movsb
	pop	ds
	inc	CurY
	mov	ax,CurY
	cmp	ax,ds:BlockEnd.Y
	ja	@@10
	jmp	@@6
@@9:	inc	ErrorOccured
@@10:	mov	cx,CurY
	dec	cx
	sub	cx,ds:BlockBeg.Y
	jb	@@12
	mov	ax,TempBufY
	mov	ds:BlockBeg.Y,ax
	add	ax,cx
	mov	ds:BlockEnd.Y,ax
	mov	ds:BlockBeg.X,1
	mov	ax,Len
	inc	ax
	mov	ds:BlockEnd.X,ax
	cmp	ErrorOccured,0
	jne	@@11
	Invoke	MoveBlockRaw
	Invoke	SetEditDS
	jnc	@@12
@@11:	Invoke	DeleteBlockRaw
	Invoke	EndCursorRaw
	Invoke	FoolBS
	Invoke	SetEditDS
	mov	ax,SaveBlockBegY
	mov	ds:BlockBeg.Y,ax
	mov	ax,SaveBlockBegX
	mov	ds:BlockBeg.X,ax
	mov	ax,SaveBlockEndX
	mov	ds:BlockEnd.X,ax
	mov	ax,SaveBlockEndY
	mov	ds:BlockEnd.Y,ax
	mov	ax,SaveCursorPosX
	mov	ds:CursorPos.X,ax
	mov	ax,SaveCursorPosY
	mov	ds:CursorPos.Y,ax
	pop	ds:Options
	jmp	@@13
@@12:	push	ds:ScreenPos.Y
	Invoke	SetTempPos
	Invoke	EndCursorRaw
	Invoke	FoolBS
	Invoke	MoveToTempPos
	Invoke	SetEditDS
	pop	ds:ScreenPos.Y
	pop	ds:Options
@@13:	Exit	CopyBlockRaw

CheckBlock	proc	near
	mov	ax,ds:BlockBeg.Y
	cmp	ax,ds:BlockEnd.Y
	je	@@2
	ja	@@3
	test	ax,ax
	jz	@@3
	xor	ax,ax
	cmp	ax,ds:BlockBeg.X
	jge	@@3
	cmp	ax,ds:BlockEnd.X
	jge	@@3
@@1:	inc	ax
	jmp	@@4
@@2:	mov	ax,ds:BlockBeg.X
	cmp	ax,ds:BlockEnd.X
	jge	@@3
	test	ax,ax
	jge	@@1
@@3:	sub	ax,ax
@@4:	ret
CheckBlock	endp

	Entry	BlockShown
	test	ds:Options,eoBlockHidden
	jnz	@@1
	call	CheckBlock
	jmp	@@2
@@1:	sub	ax,ax
@@2:	Exit	BlockShown

	Entry	BlockPresent
	call	CheckBlock
	Exit	BlockPresent

	end
