	load	'macros.dump'
	include	'driver.equ'
	include	'wp.equ'
	include	'scrap.equ'

;-----------------------------------------------
;
;	Imported	addresses
;
;-----------------------------------------------

	IMPORT	D_BeachBall
	IMPORT	W_CalcFBytes
	IMPORT	W_FindFont
	IMPORT	W_FindFont2
	IMPORT	W_GetAddr
	IMPORT	W_GetEndPar
	IMPORT	W_Getparrec
	IMPORT	W_LessRoom
	IMPORT	W_MakeRoom
	IMPORT	D_NeedHandle
	IMPORT	W_WriteFBytes
	IMPORT	W_addr
	import	W_RulBytes
	import	X_MassageWPScrap
	import	D_NeedHand
	import	D_Deref
	import	D_GrowHandle
	import	X_DisposeWPScrap


****************************************************************
*
*   W_WpCopy(startp,startl,starto,endp,endl,endo):wpscrap
*
****************************************************************
W_WpCopy	PROC	EXPORT

BlockSize	equ	$c00	;3K

	input	Startp:w,Startl:w,Starto:w
	input	Endp:w,Endl:w,Endo:w
	
	local	Pars:w,Par:w,Block:l,ParPtr:l,Sptr:l,ParRec:l,Type:w
	local	Length:w,Offset:w,Bptr:l,NewOffset:l,CurrentBlock:l
	local	CBPtr:l,NewRuler:l,NRPtr:l,Ruler:l,OldRuler:l,BlockUsed:w
	local	ScrapSize:l,NextBlock:l,NewSize:l,Soff:l
	
	output	Scrap:l

	error	err

	begin	+b
	stz	err
	
	SubWord	Endp,Startp,Pars
	inc	Pars
	
	tool	_Multiply,in=(Pars:w,#W_pBytes:w),out=(:l)
	AddLong	s,#2,ScrapSize
	call	D_NeedHand,in=ScrapSize:l,out=Scrap:l,err=err
	jcs	exit
	
	MoveLong	[Scrap],Sptr
	MoveWord	#0,[Sptr]

	MoveLong	#2,Soff
	MoveWord	Startp,Par
	Stzl	Block
	Stzl	OldRuler

parloop
	jsl	D_BeachBall
	jsr	GetParInfo		;ParRec will have pointer to 
				;paragraph,Type will be set,returns
				;length of paragraph Length, and offset
				;to first character in Offset.

	jsr	GrowBlock		;Will allocate a new block if there
	jcs	memoryerror		;is none.  Will make space if there
				;would still be less than 3K.  Will
				;make new text block if not.  Sets
				;up the variables Block,Bptr,NewOffset.
				;Uses Length variable.  Does NOT lock
				;the block.

	MoveLong	[ParRec],CurrentBlock
	MoveLong	[CurrentBlock],CBPtr
	Addwl	Offset,CBPtr
	Cmpw	Par,StartP
	bne	nofont
	
;Get font info for the first paragraph
	call	W_FindFont,in=(Startp:w,Startl:w,Starto:w),out=(:l,:w)
	PullWord	[Bptr]:#4	;Color
	PullLong	[Bptr]	;Font ID
	Addwl	#7,Bptr
	bra	docopy

nofont	lda	[CBPtr]
	sta	[Bptr]
	ldy	#2
	lda	[CBptr],y
	sta	[Bptr],y
	iny
	iny
	lda	[CBptr],y
	sta	[Bptr],y
	Addwl	#7,CBptr
	Addwl	#7,Bptr
	Subwl	#7,Length

docopy
;Now set up the copying of text.
	jsr	CopyText

;Copy the ruler if necessary.
	lda	Type
	bne	noruler

	MoveLong	[ParRec]:#W_pRulerHand,Ruler
	Cmpl	Ruler,OldRuler
	bne	getnewruler
	MoveLong	[NewRuler],NRPtr
	lda	[NRPtr]
	inc	a
	sta	[NRPtr]
	bra	noruler
	
getnewruler
	call	D_NeedHand,in=(#W_RulBytes:l),out=(NewRuler:l),err=err
	bcc	@1
	jsr	DisposeCurrentBlock	;Only disposes if nothing else has used it.
	brl	memoryerror
@1

	MoveLong	[NewRuler],NRPtr
	tool	_BlockMove,in=([Ruler]:l,NRPtr:l,#W_RulBytes:l)
	MoveWord	#1,[NRPtr]
	MoveLong	Ruler,OldRuler
	bra	update

noruler	Stzl	Ruler

update
;Update the paragraph array.  This is used for all paragraphs
	MoveLong	[Scrap],Sptr
	AddLong	Sptr,Soff,ParPtr
	Addwl	#W_pBytes,Soff
	MoveLong	Block,[ParPtr]
	MoveWord	NewOffset,[ParPtr]:#W_pOffset
	MoveWord	Type,[ParPtr]:#W_pAttr
	MoveLong	NewRuler,[ParPtr]:#W_pRulerHand
	MoveWord	#0,[ParPtr]:#W_PRulerHand+4
	MoveWord	a,[ParPtr]:#W_PRulerHand+6
	MoveWord	a,[ParPtr]:#W_PRulerHand+8
	MoveWord	a,[ParPtr]:#W_PRulerHand+10
	lda	[Sptr]
	inc	a
	sta	[Sptr]
	Cmpw	Par,Endp
	bge	massage
	inc	Par
	brl	parloop	

massage	call	X_MassageWPScrap,in=(Scrap:l)
	bra	exit

memoryerror	call	X_DisposeWPScrap,in=Scrap:l

exit	return

;This sets up several variables about the paragraph in Par.  Length will be the size
;of the text.  ParRec wil be the pointer to the paragraph record.  OldTextPtr will
;point to the first character of text past the paragraph header.  Offset will be
;the offset into the block for this character.  Type will be the type of paragraph.
;Length includes the carraige return.

GetParInfo	rcall	W_GetParRec,in=(Par:a),out=(ParRec:ax) ;input paragraph in Par
	stz	Length
	MoveWord	[ParRec]:#W_pAttr,Type
	MoveWord	[ParRec]:#W_pOffset,Offset

;Find the end of the paragraph by subtracting offsets.

;Is this the first paragraph?
	Cmpw	Par,Startp
	bne	notfirst
	AddWord	StartO,Offset,Offset	
notfirst	

;Is this the last?  Then this is simple.
	Cmpw	Par,Endp
	bne	notlast
	cmpw	Par,StartP
	bne	@1
	Subword	EndO,StartO,Length	;fucking special cases !
	rts
@1
	MoveWord	EndO,Length
	rts

;Note: Since this is not the last paragraph in the selection, it is not the last
;paragraph in the document.  This takes care of one special case.

;If the next paragraph is in the same block, we subtract the offsets of the two paragraphs.
notlast	MoveLong	[ParRec],CurrentBlock
	MoveLong	[ParRec]:#W_pBytes,NextBlock
	Cmpl	CurrentBlock,NextBlock
	bne	notsameblock
	
	SubWord	[ParRec]:#W_PBytes+W_pOffset,Offset,Length
	rts

;If not, we subtract the start offset from the used field in the text block.
notsameblock
	MoveLong	[CurrentBlock],CBPtr
	SubWord	[CBPtr]:#2,Offset,Length
	rts

;Will allocate a new block if there is none.  Will make space if there would still
;be less than 3K.  Will make new text block if not.  Sets up the variables Block,
;Bptr,NewOffset.  Uses Length variable.  Does NOT lock the block.  If it is the last
;paragraph, one is added to the size for the carriage return.
GrowBlock	Cpzl	Block
	beq	newblock
	MoveLong	[Block],Bptr
	AddWord	Length,[Bptr],NewSize
	Cmpw	Par,EndP
	bne	nocrroom
	inc	NewSize
nocrroom	Cmpw	NewSize,#BlockSize
	jge	newblock

	inc	BlockUsed
	call	D_GrowHandle,in=(#0:w,NewSize:w,Block:l),err=err
	bcc	@1
	rts
@1
	MoveLong	[Block],Bptr
	MoveWord	[Bptr],NewOffset
	MoveWord	NewSize,[Bptr]
	MoveWord	a,[Bptr]:#2
	Addwl	NewOffset,Bptr
	clc
	rts
	
newblock
;This is the first allocation
	stz	BlockUsed
	AddWord	Length,#4,NewSize
	Cmpw	Par,StartP
	bne	@3
	Addwl	#7,NewSize
@3	Cmpw	Par,Endp
	bne	@2
	inc	NewSize
@2
	call	D_NeedHand,in=(#0:w,NewSize:w),out=(Block:l),err=err
	bcc	@1
	rts
@1	MoveLong	[Block],Bptr
	MoveWord	NewSize,[Bptr]
	MoveWord	a,[Bptr]:#2
	MoveWord	#4,NewOffset
	Addwl	#4,Bptr
	clc
	rts

;Disposes of current block if it has never been grown.
DisposeCurrentBlock
	lda	BlockUsed
	bne	@1
	tool	_DisposeHandle,in=(Block:l)
@1	rts
	
;Copies text from CBptr to Bptr filtering out date pages and time
CopyText	ldy	#0
	shortm
loop	lda	Length
	ora	Length+1
	beq	addcr
	lda	[CBptr],y
	sta	[Bptr],y
	cmp	#CR+1
	blt	special
notspecial	iny
	lda	Length
	bne	@1
	dec	Length+1
@1	dec	Length
	bra	loop
special	cmp	#CR
	beq	docr
	cmp	#8
	bge	notspecial
	cmp	#5
	blt	changes
	lda	#' '
	sta	[Bptr],y
	bra	notspecial
changes	cmp	#1
	beq	dofont
dotwo	longm
	lda	[CBptr],y
	sta	[Bptr],y
	iny
	iny
	SubWord	Length,#2,Length
	shortm
	bra	loop
dofont	iny
	lda	Length
	bne	@1
	dec	Length+1
@1	dec	Length
	bra	dotwo
	
addcr	lda	#CR
	sta	[BPtr],y
docr	longm
	rts
	
	
	ENDP

*****************************************************************************************************
; W_PasteAscii ( textptr:long, textlen:word, paragraph:word, offset:word )
;
;   This routine is called to quickly paste text at the given location, without remaking the line
; handles. The text must not contain carriage returns.
;
; Note: Can return memory errors.

W_PasteAscii PROC	EXPORT

	input	txtptr:l,txtlen:w,par:w,off:w
	local	addr:l
	error	err
	begin

	stz	err
	lda	txtlen
	beq	exit
	call	W_MakeRoom,in=(par:w,off:w,txtlen:w),err=err
	bcs	exit
	
	rcall	W_GetAddr,in=(par:a,off:x),out=(addr:ax)
	tool	_BlockMove,in=(txtptr:l,addr:l,#0:w,txtlen:w)

exit	return

	ENDP

****************************************************************
*
* W_DeleteText(par:w,soff:w,eoff:w)	-- quickly delete the text
*	between the two limits, without recomputing the line
*	handles.
*
****************************************************************
W_DeleteText	PROC	EXPORT

	input	par:w,soff:w,eoff:w
	local	sfont:l,scolor:w,efont:l,ecolor:w,fbytes:w

	begin

	cmpw	soff,eoff
	jeq	exit

	spaceword
	spacelong
	pushword	par
	pushword	soff
	jsl	W_FindFont2
	pulllong	sfont
	pullword	scolor

	spaceword
	spacelong
	pushword	par
	pushword	eoff
	jsl	W_FindFont2
	pulllong	efont
	pullword	ecolor

	spaceword
	pushlong	sfont
	pushword	scolor
	pushlong	efont
	pushword	ecolor
	jsl	W_CalcFBytes
	pullword	fbytes

	pushword	par
	pushword	soff
	lda	eoff
	sec
	sbc	soff
	sbc	fbytes
	pha
	jsl	W_LessRoom

	lda	par
	ldx	soff
	jsl	W_GetAddr
	pushlong	ax
	pushlong	sfont
	pushword	scolor
	pushlong	efont
	pushword	ecolor
	jsl	W_WriteFBytes

exit	return

	ENDP
	END

