*****************************************************************************************************
* WP Scrap Routines
* 
*    This file contains the routines to create and manipulate WP scraps.
*
*****************************************************************************************************

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

	IMPORT	D_GrowHandle
	IMPORT	D_NeedHand
	IMPORT	D_NeedHandle

	IMPORT	X_CopyThread
	IMPORT	X_DBtoPLScrap
	IMPORT	X_DisposeThread
	IMPORT	X_PLtoWPScrap
	IMPORT	X_ParBlockSize
	IMPORT	X_RulerSize
	IMPORT	X_ScrStdRuler
	IMPORT	X_SStoPLScrap

	ENTRY	X_StdTabRuler
	ENTRY	X_SwitchFontID

*****************************************************************************************************
; X_DisposeWPScrap ( Scrap:long )
;
;   This routine is called to dispose of the given WP scrap. This routine is just a WP front end to
; DisposeThread which does the real work.

X_DisposeWPScrap	PROC	EXPORT
	;Using X_WPScrapData

	input 	Scrap:l
	begin

	call	X_DisposeThread,in=(Scrap:l,#0:w)
	return
	
	ENDP

*****************************************************************************************************
; X_CopyWPScrap ( Scrap:long ):Dest:long
;
;   This routine is called to create a copy of the given WP scrap.  This routine is just a WP front
; end to CopyThread which does the real work.

X_CopyWpScrap	PROC	EXPORT

	input 	Scrap:l
	output 	Dest:l
	error 	err
	begin

	call	X_CopyThread,in=(Scrap:l,#0:w),out=(Dest:l),err=err
	return

	ENDP

*****************************************************************************************************
; X_MassageWPScrap ( Scrap:long )
;
;   This routine will make sure to separate the first and last paragraphs into their own text blocks.
; Memory errors will be returned.

X_MassageWPScrap	PROC	EXPORT
	;Using X_WPScrapData
	;Using X_WPFileData

	input 	Src:l
	local 	Sptr:l,Bpars:w,Block:l,Bptr:l,ParSize:l
	local 	BlockSize:l,NBPtr:l,Offset:w
	local 	NextOffset:l,NewParOffset:w,NewBlock:l
	local 	LastBlock:l,OBPtr:l
	error 	err
	begin

; Clear error status and lock down the source scrap handle. Get pointer to start of source scrap and
; count for the number of paragraphs in the scrap. If only one paragraph exists in the scrap then
; we are done.

	stz 	err
	tool	_HLock,in=(Src:l)
	movelong 	[Src],Sptr
	moveword 	[Sptr],Bpars
	cmp	#1
	jeq	exit

; Check to see if the first two paragraphs are in the same block. If they are not then branch to
; check last paragraphs.

	addwl	#2,Sptr
	movelong	[SPtr],Block
	cmpl	Block,[SPtr]:#X_ParBlockSize
	jne	lastpar
	moveword	#X_ParBlockSize,NewParOffset
	
; If they are then, figure out size of first paragraph by subtracting text block offsets between it
; and the next paragraph.

	moveword	[SPtr]:#X_scpOffset,Offset
	moveword	[SPtr]:#X_scpOffset+X_ParBlockSize,NextOffset
	stz	ParSize+2
	subword	NextOffset,Offset,ParSize

; Allocate new block for the first paragraph.

	lda	ParSize
	clc
	adc	#4
	tax
	call	D_NeedHandle,in=(#0:w,x:w,#X_Locked:w),out=(NewBlock:l),err=err
	jcs	exit

; Put size and used bytes information at beginning of text block then bump NBPtr past it.

	movelong	[NewBlock],NBPtr
	addword	ParSize,#4,[NBPtr]
	moveword	a,[NBPtr]:#2
	addwl	#4,NBPtr

; Move the first paragraph text into its new text block.

	tool	_Hlock,in=(Block:l)
	movelong 	[Block],Bptr
	lda 	Bptr
	clc
	adc 	#4
	tax
	lda 	Bptr+2
	adc 	#0
	pha
	phx
	PushLong 	NBPtr
	PushLong 	ParSize
	_BlockMove

; Determine what the size of the original text block would be minus the first paragraph text.

	subword	[BPtr],ParSize,BlockSize
	stz 	BlockSize+2

; Now move text starting @ text offset for next paragraph down to where the first paragraphs text
; used to be. (Don't count the size words (4 bytes) at the start of the text block).

	lda 	Bptr
	clc
	adc 	NextOffset
	tax
	lda 	Bptr+2
	adc 	#0
	pha
	phx			; source
	lda 	Bptr
	clc
	adc 	#4
	tax
	lda 	Bptr+2
	adc 	#0
	pha
	phx			; dest
	lda 	BlockSize
	sec
	sbc 	#4
	tax
	lda 	BlockSize+2
	sbc 	#0
	pha
	phx			; size
	_BlockMove

; Change to size of the old text block to reflect its shrinking then size it down.

	subword	[BPtr],ParSize,[BPtr]
	subword	[BPtr]:#2,ParSize,[BPtr]:#2
	tool	_HUnlock,in=(Block:l)
	tool	_SetHandleSize,in=(BlockSize:l,Block:l)

; Now go through and adjust all the paragraph offsets for all the paragraphs which shared the text
; block we just changed. Replace first paragraphs text block with the new one.

	movelong	NewBlock,[Sptr]
	ldx 	#1
changeloop	addwl	#X_ParBlockSize,Sptr
	cmpl	[SPtr],Block
	bne 	endloop
	subword	[SPtr]:#X_scpOffset,ParSize,[SPtr]:#X_scpOffset
	inx
	cpx 	Bpars
	blt 	changeloop
endloop

; Make sure last paragraph has a text block of its own. If only two paragraphs then we are done.

lastpar	cmpw	BPars,#2
	jeq	exit
	
; Get pointer to last paragraph and second to last paragraph entries in the scrap. If the paragraphs
; have different text blocks then we are done.

	lda	BPars
	dec	a
	tool	_Multiply,in=(a:w,#X_ParBlockSize:w),out=(LastBlock:l)
	addlong 	[Src],LastBlock,Sptr
	addwl 	#2,Sptr
	sublong 	Sptr,#X_ParBlockSize,OBPtr
	cmpl 	[Sptr],[OBPtr]
	jne 	exit

; Get the size of the last paragraphs text.

	movelong 	[Sptr],Block
	movelong 	[Block],Bptr
	moveword 	[Bptr]:#2,a
	subword 	a,[Sptr]:#X_scpOffset,ParSize
	stz 	ParSize+2

; Try to create a new paragraph text block for it. If we fail then exit with scrap still intact but
; last paragraph still shares text block with second to last paragraph.

	addwl 	#4,ParSize
	call	D_NeedHand,in=(ParSize:l),out=(NewBlock:l),err=err
	jcs	exit
	subwl	#4,ParSize
	
; Adjust text blocks size to no longer include the last paragraphs text. { Note we also collapse the
; text block in the process so its size will be the same as its used }

	subword 	[Bptr]:#2,ParSize,[Bptr]:#2
	sta 	[Bptr]
	sta 	BlockSize
	stz 	BlockSize+2

; Set new text blocks total size and used size to the last paragraph's text size. Point past size
; information for the new block. Get pointer to start of last paragraph's text in the old text
; block.

	movelong 	[NewBlock],NBptr
	addword	ParSize,#4,[NBPtr]
	moveword	a,[NBPtr]:#2
	addwl 	#4,NBPtr
	movelong 	[Block],Bptr
	moveword 	[Sptr]:#X_scpOffset,a
	addwl	a,BPtr

; Move last paragraph's text from the old block to the new block then shrink the old block to its
; new size.

	tool	_BlockMove,in=(BPtr:l,NBPtr:l,ParSize:l)
	call	D_GrowHandle,in=(BlockSize:l,Block:l)

; Change last paragraph information in the scrap to reflect its new text block.

	movelong 	NewBlock,[Sptr]
	moveword 	#4,[Sptr]:#X_scpOffset

; Unlock source handle before returning to caller.

exit	tool	_HUnlock,in=(Src:l)
	return

	ENDP

*****************************************************************************************************
; X_DBtoWPScrap ( DBScrap:long ):WPScrap:long
;
;   This routine is called to convert database scraps to word processing scraps. It uses the page
; layout conversion routines to do the job.

X_DBtoWPScrap	PROC	EXPORT
	;Using X_WPFileData
	;Using X_TabRulerData

	input 	Src:l
	local 	Ruler:l,Rptr:l,Dptr:l,Pars:w,Intermed:l
	output 	Dest:l
	error 	err
	begin

; Convert DBScrap to PL and then to WP. Handle memory errors.

	call	X_DBtoPLScrap,in=(Src:l),out=(Intermed:l),err=err
	bcs	exit
	call	X_PLtoWPScrap,in=(Intermed:l),out=(Dest:l),err=err
	bcs	killinter

; Copy ruler count to standard ruler template and then replace ruler with standard ruler.

	movelong 	[Dest],Dptr
	movelong	[DPtr]:#(X_scpRulerHand+2),Ruler
	movelong 	[Ruler],Rptr
	moveword 	[Rptr],X_StdTabRuler
	tool	_BlockMove,in=(#X_StdTabRuler:l,Rptr:l,#X_RulerSize:l)

; Dispose of intermediate handle and return to caller.

killinter	tool	_DisposeHandle,in=(Intermed:l)
exit	return

	ENDP

*****************************************************************************************************
; X_SStoWPScrap ( SSScrap:long ):WPScrap:long
;
;   This routine is called to convert spreadsheet scraps to word processing scraps. It uses the page
; layout conversion routines to do the job.

X_SStoWPScrap	PROC	EXPORT
	;Using X_WPFileData
	;Using X_TabRulerData

	input 	Src:l
	local 	Dptr:l,Ruler:l,Rptr:l,Intermed:l
	output 	Dest:l
	error 	err
	begin

; Convert SSScrap to PL and then to WP. Handle memory errors.

	call	X_SStoPLScrap,in=(Src:l),out=(Intermed:l),err=err
	bcs	exit
	call	X_PLtoWPScrap,in=(Intermed:l),out=(Dest:l),err=err
	bcs	killinter
	
; Copy ruler count to standard ruler template and then replace ruler with standard ruler.

	movelong 	[Dest],Dptr
	movelong 	[Dptr]:#(X_scpRulerHand+2),Ruler
	movelong 	[Ruler],Rptr
	moveword 	[Rptr],X_StdTabRuler
	tool	_BlockMove,in=(#X_StdTabRuler:l,Rptr:l,#X_RulerSize:l)

; Dispose of intermediate handle and return to caller.

killinter	tool	_DisposeHandle,in=(Intermed:l)
exit	return

	ENDP

*****************************************************************************************************
; X_SwitchFont ( Font:long, Color:word, Scrap:long )
;
;    Set the default font and color for the given WP scrap. The real work is done by X_SwitchFontID.

X_SwitchFont	PROC	EXPORT

	input 	Font:l,Color:w,Handle:l
	begin

	call	X_SwitchFontId,in=(Font:l,Color:w,Handle:l,#0:w)
	return

	ENDP


*****************************************************************************************************
; X_SwitchFontID ( Font:long, Color:word, Scrap:long, Type:word )
;
;    Set the default font and color for the given scrap if its font/color/style is currently
; undefined (-1). If type is non-zero then assume scrap is of
; PL type. 

X_SwitchFontID	PROC	EXPORT
	;Using X_WPFileData
	;Using X_WPScrapData

	input 	font:l,color:w,handle:l,type:w
	local 	ParRec:l,pars:w,Block:l,Ptr:l,offset:l
	local 	StyleChange:w,ParSize:l
	begin

; Set paragraph block size depending on whether this is a WP or PL scrap. { PL paragraph blocks are
; 4 bytes bigger }.

	movelong	#X_ParBlockSize,ParSize
	lda 	type
	beq 	cont
	addwl	#4,ParSize

; Get the number of paragraphs in the scrap. Point to first paragraph entry in the scrap.

cont	movelong 	[handle],ParRec
	moveword 	[ParRec],pars
	addwl	#2,ParRec

; Get text block for first paragraph in scrap and pointer to text block.

	movelong 	[ParRec],Block
	movelong 	[Block],Ptr

; Check if font information is set to -1 if not then font does not need to be switched in - exit.

	cmpw 	[Ptr]:#4,#-1
	jne 	exit

; Check if style needs to be changed if so set flag.

	stz	StyleChange
	ldy 	#6
	lda 	[Ptr],y
	and	#$00FF
	cmp 	#$00FF
	bne 	startup
	inc 	StyleChange

; Loop through all paragraphs in the scrap and change their text blocks to contain the new font and
; color (possible style too) information. If Type is WP then make sure to ignore page breaks.

startup	stz 	offset+2
PLoop	lda 	Type
	bne 	dochange
	ldy 	#X_scpAttr
	lda 	[ParRec],y
	bne 	nextp

; Point to font/style/color info in the paragraph's text block.

dochange	movelong 	[ParRec],Block
	moveword 	[ParRec]:#X_scpOffset,offset
	addlong 	[Block],offset,Ptr

; Replace the old font/style/color info with the new info. { only change style if flag set }.

	moveword 	font,[Ptr]
	moveword 	color,[Ptr]:#4
	lda 	StyleChange
	shortm
	beq 	nochange
	moveword 	font:#2,[Ptr]:#2
nochange	moveword 	font:#3,[Ptr]:#3
	longm

; Go to next paragraph. If all paragraphs done then exit.

nextp	addwl 	ParSize,ParRec
	dec 	pars
	bne 	PLoop

exit	return

	ENDP

*****************************************************************************************************
; X_TabRulerData ( )
;
;   This is the standard ruler used by the scrap routines. 

X_TabRulerData	PROC	EXPORT
	
	EXPORT	X_StdTabRuler

X_StdTabRuler	
	DS.B 	2			; { ruler count goes here }
	DC.W	X_scr_r_left+X_scr_r_single	; status
	DC.W	40			; left margin
	DC.W	40			; indent margin
	DC.W	560			; right margin
	DC.W	6			; number of tabs
	DC.W	120			; tab location
	DC.W	X_scr_rt_left		; tab type
	DC.W	200			; tab location
	DC.W	X_scr_rt_left		; tab type
	DC.W	280			; tab location
	DC.W	X_scr_rt_left		; tab type
	DC.W	360			; tab location
	DC.W	X_scr_rt_left		; tab type
	DC.W	440			; tab location
	DC.W	X_scr_rt_left		; tab type
	DC.W	520			; tab location
	DC.W	X_scr_rt_left		; tab type
	DC.W	0
	DC.W	0
	DC.W	0
	DC.W	0
	DC.W	0
	DC.W	0
	DC.W	0
	DC.W	0

	ENDP

*****************************************************************************************************
; X_MakeStandardRuler ( )
;
;   This routine is called to initialize X_ScrStdRuler to a default ruler with only 1 tab.

X_MakeStandardRuler	PROC	EXPORT

	begin	+b
	tool	_BlockMove,in=(#Defaults:l,#X_ScrStdRuler:l,#X_RulerSize:l)
	return

Defaults	DS.B 	2			; (ruler count goes here)
	DC.W	X_scr_r_left+X_scr_r_single	; status
	DC.W	40			; left margin
	DC.W	40			; indent margin
	DC.W	560			; right margin
	DC.W	1			; number of tabs
	DC.W	350			; tab location
	DC.W	X_scr_rt_left		; tab type
	DC.W	0
	DC.W	X_scr_rt_left
	DC.W	0
	DC.W	X_scr_rt_left
	DC.W	0
	DC.W	X_scr_rt_left
	DC.W	0
	DC.W	X_scr_rt_left
	DC.W	0
	DC.W	X_scr_rt_left
	DC.W	0
	DC.W	X_scr_rt_left
	DC.W	0
	DC.W	X_scr_rt_left
	DC.W	0
	DC.W	X_scr_rt_left
	DC.W	0
	DC.W	X_scr_rt_left

	ENDP

*****************************************************************************************************
; X_TenthsTo80ths ( )
;
;    Multiply by 8 routine.

X_tenthsto80ths	PROC	EXPORT
	asl 	a
	asl 	a
	asl 	a
	and 	#$fffc
	rtl
	ENDP
	
	END

