mirror of
https://github.com/antoinevignau/source.git
synced 2024-11-19 07:31:13 +00:00
1 line
37 KiB
Plaintext
Executable File
1 line
37 KiB
Plaintext
Executable File
*****************************************************************************************************
|
|
; WP Paragraph Manipulation Routines
|
|
;
|
|
; This file contains the routines used to manipulate the paragraph data structure used by WP. The
|
|
; paragraph structure is described below:
|
|
;
|
|
; The paragraph data structure is an array from 1..W_LastP of paragraph info blocks:
|
|
;
|
|
; W_pBlockHand gequ 0 : handle to the block that the par is in
|
|
; W_pOffset gequ 4 : offset into this block that starts the par
|
|
; W_pAttr gequ 6 : attribute word for the par
|
|
; W_pRulerHand gequ 8 : handle to the ruler that governs this par
|
|
; W_pPixels gequ 12 : number of pixels tall this par is
|
|
; W_pLineHand gequ 14 : handle to the line struct for this par (Purgeable)
|
|
; W_pLastLine gequ 18 : number of last line in the par+1, cr is 0
|
|
; W_pBytes gequ 20 : equate for size of paragraph block.
|
|
;
|
|
*****************************************************************************************************
|
|
|
|
load 'macros.dump'
|
|
include 'driver.equ'
|
|
include 'wp.equ'
|
|
|
|
W_StartMaxP equ 10
|
|
W_StartBlockSize equ $1000
|
|
W_GrowAmount equ $400
|
|
|
|
IMPORT D_SetFileChanged
|
|
IMPORT D_Deref
|
|
IMPORT D_GrowHandle
|
|
IMPORT D_GrowLHandle
|
|
IMPORT D_MainZPage
|
|
IMPORT D_NeedHand
|
|
|
|
IMPORT W_CurDoc
|
|
IMPORT W_FindFont
|
|
IMPORT W_GetLRecPtr
|
|
IMPORT W_GetLineRec
|
|
IMPORT W_LastP
|
|
IMPORT W_MakeLines
|
|
IMPORT W_MaxP
|
|
IMPORT W_PHandle
|
|
IMPORT W_PPtr
|
|
|
|
IMPORT W_RulBits
|
|
IMPORT W_RulBytes
|
|
IMPORT W_Selected
|
|
|
|
IMPORT W_StartLine
|
|
IMPORT W_StartOffset
|
|
IMPORT StdRuler
|
|
IMPORT W_StartPar
|
|
IMPORT W_ValidLines
|
|
IMPORT W_WPRuler
|
|
IMPORT W_Stuff
|
|
|
|
ENTRY W_GetAddr
|
|
ENTRY W_GetLastLGuts
|
|
ENTRY W_GetParRec
|
|
ENTRY W_LessRoom
|
|
ENTRY W_MakeEmptyBlock
|
|
ENTRY W_MakeNewParRec
|
|
ENTRY W_MakeRoom
|
|
ENTRY W_NewRuler
|
|
ENTRY W_UseRuler
|
|
|
|
*****************************************************************************************************
|
|
; W_InitPars ( )
|
|
;
|
|
; This routine is called to setup and empty document. It will create a new paragraph array and a
|
|
; single carriage return paragraph.
|
|
;
|
|
; Note: Memory errors are returned.
|
|
|
|
W_InitPars PROC EXPORT
|
|
;Using wpglobals
|
|
;Using W_ParData
|
|
|
|
local ptr:l,TextPtr:l,RulerHand:l,TextBlock:l
|
|
error err
|
|
begin
|
|
|
|
; Ask for initial paragraph array handle. If memory error then exit with error.
|
|
|
|
call D_NeedHand,in=(#W_StartMaxP*W_pBytes:l),out=(ax:l),err=err
|
|
jcs exit
|
|
|
|
; Lock down paragraph handle and get pointer to first paragraph entry.
|
|
|
|
movelong ax,W_PHandle
|
|
jsl D_Deref
|
|
movelong ax,W_PPtr
|
|
moveword #W_StartMaxP,W_MaxP
|
|
moveword #1,W_LastP
|
|
rcall W_GetParRec,in=(#1:a),out=(ptr:ax)
|
|
|
|
; Get text block for 1st paragraph.
|
|
|
|
call W_MakeEmptyBlock,out=(TextBlock:l),err=err
|
|
jcs @killpar
|
|
movelong TextBlock,[ptr]
|
|
|
|
; Initialize 1st paragraph entry in paragraph array.
|
|
|
|
moveword #W_BHeader,[ptr]:#W_pOffset
|
|
moveword #0,[ptr]:#W_pAttr
|
|
movelong #0,[ptr]:#W_pLineHand
|
|
moveword #1,[ptr]:#W_pLastLine
|
|
|
|
; Get ruler for 1st paragraph. If memory error then clean up and exit with error. Else use ruler.
|
|
|
|
call W_NewRuler,out=(RulerHand:l),err=err
|
|
bcs @killtext
|
|
movelong RulerHand,[Ptr]:#W_pRulerHand
|
|
call W_UseRuler,in=(#1:w,RulerHand:l)
|
|
|
|
; Make room for initial text block contents - if error then clean up and exit.
|
|
|
|
call W_MakeRoom,in=(#1:w,#0:w,#W_TextHeader+1:w),err=err
|
|
bcs @killruler
|
|
|
|
; Set up contents of 1st paragraph text block - single carriage return.
|
|
|
|
rcall W_GetAddr,in=(#1:a,#0:x),out=(TextPtr:ax)
|
|
moveword #W_StandFont,[TextPtr]
|
|
moveword #W_StandStyle,[TextPtr]:#2
|
|
moveword #Black,[TextPtr]:#4
|
|
movebyte #cr,[TextPtr]:#W_TextHeader
|
|
|
|
; Create lines for 1st paragraph and initialize globals. If we can't make lines then return memory
|
|
; error.
|
|
|
|
call W_MakeLines,in=(#1:w),err=err
|
|
bcs @killruler
|
|
stz W_StartLine
|
|
stz W_Selected
|
|
moveword #1,W_StartPar
|
|
moveword #W_TextHeader,W_StartOffset
|
|
bra exit
|
|
|
|
; Memory error occurred so clean up allocated memory.
|
|
|
|
@killruler tool _DisposeHandle,in=(RulerHand:l)
|
|
@killtext tool _DisposeHandle,in=(TextBlock:l)
|
|
@killpar tool _DisposeHandle,in=(W_PHandle:l)
|
|
|
|
exit return
|
|
|
|
|
|
ENDP
|
|
|
|
****************************************************************
|
|
* W_GetAddr - returns the physical address of par a, offset x
|
|
* returns address in ax
|
|
W_GetAddr PROC EXPORT
|
|
;Using D_GlobalData
|
|
ParRec equ 0
|
|
handle equ 4
|
|
ptr equ 8
|
|
|
|
tay
|
|
phd
|
|
lda >D_MainZPage
|
|
tcd
|
|
phx ;D_Save offset for later
|
|
|
|
tya
|
|
jsl W_GetParRec
|
|
movelong ax,ParRec
|
|
|
|
movelong [ParRec],handle
|
|
movelong [handle],ptr
|
|
|
|
ldx ptr+2
|
|
|
|
ldy #W_pOffset
|
|
lda [ParRec],y
|
|
clc
|
|
adc ptr
|
|
bcc NoInc
|
|
inx
|
|
clc
|
|
NoInc adc 1,s
|
|
bcc NoInc2
|
|
inx
|
|
|
|
NoInc2 ply
|
|
pld
|
|
rtl
|
|
|
|
ENDP
|
|
|
|
|
|
|
|
|
|
****************************************************************
|
|
* W_GetParRec - gets the physical address of par a's record structure
|
|
* adress is returned in ax
|
|
* NOTE!!! this must be changed as W_pBytes is changed. Hard-wired.
|
|
W_GetParRec PROC EXPORT
|
|
;Using wpglobals
|
|
;Using D_GlobalData
|
|
|
|
tay
|
|
phd
|
|
lda >D_MainZPage
|
|
tcd
|
|
|
|
ldx W_PPtr+2
|
|
|
|
tya
|
|
dec a ;since pars start with 1
|
|
asl a
|
|
asl a
|
|
sta 2 ;the times 4 part
|
|
|
|
asl a
|
|
bcc NoInca
|
|
inx ;if over here, takes 2 inx
|
|
inx
|
|
NoInca
|
|
asl a ;the times 16 part
|
|
bcc NoInc
|
|
inx
|
|
clc
|
|
NoInc
|
|
adc 2 ;add times4 with times16
|
|
bcc NoInc2
|
|
inx
|
|
clc
|
|
NoInc2
|
|
adc W_PPtr ;add to Par ptr offset
|
|
bcc NoInc3
|
|
inx
|
|
NoInc3
|
|
pld
|
|
rtl
|
|
|
|
ENDP
|
|
|
|
|
|
*****************************************************************************************************
|
|
; W_MakeEmptyBlock ( ): BlockHandle:long
|
|
;
|
|
; This routine is called to allocate a new empty text block and initializes its header counts.
|
|
|
|
W_MakeEmptyBlock PROC EXPORT
|
|
;Using W_ParData
|
|
|
|
output BlockHand:l
|
|
local ptr:l
|
|
error err
|
|
begin
|
|
|
|
call D_NeedHand,in=(#W_StartBlockSize:l),out=(ax:l),err=err
|
|
bcs @exit
|
|
movelong ax,BlockHand
|
|
movelong [BlockHand],ptr
|
|
moveword #W_StartBlockSize,[ptr]:#W_BSize
|
|
moveword #W_BHeader,[ptr]:#W_BUsed
|
|
|
|
@exit return
|
|
|
|
ENDP
|
|
|
|
*****************************************************************************************************
|
|
; W_DoRoom ( Paragraph:word, Offset:word, Bytes:word )
|
|
;
|
|
; This routine is called to adjust the given paragraph's text block by the given number of bytes.
|
|
; Bytes is a signed number possibly negative. If negative then call LessRoom, else use MakeRoom.
|
|
|
|
W_DoRoom PROC EXPORT
|
|
|
|
lda 4,s ;look at bytes
|
|
bpl W_MakeRoom
|
|
eor #$ffff ; negate into a positive value to pass LessRoom.
|
|
inc a
|
|
sta 4,s
|
|
brl W_LessRoom
|
|
|
|
ENDP
|
|
|
|
*****************************************************************************************************
|
|
; W_MakeRoom ( Paragraph:word, Offset:word, Bytes:word )
|
|
;
|
|
; This routine is called to make a gap in the text for the given paragraph, at the given offset,
|
|
; of Bytes in size. If insufficient space exists in the block then it will be split or grown as
|
|
; needed. Memory errors are returned.
|
|
;
|
|
; Note: Assumes affected blocks are unlocked.
|
|
|
|
W_MakeRoom PROC EXPORT
|
|
;Using wpglobals
|
|
;Using W_ParData
|
|
EXPORT NotLast
|
|
EXPORT W_CurrentBlockHandle
|
|
EXPORT W_CurrentBlockHandle2
|
|
|
|
input par:w,offset:w,bytes:w
|
|
local BlockPtr:l,BlockHand:l,newsize:w,ParPtr:l,LastParPtr:l
|
|
local used:w,newmax:w,BlockHand2:l,BlockPtr2:l,ParPtr2:l
|
|
local addbytes:w,CurPar:w
|
|
error err
|
|
begin
|
|
|
|
; Clear error status and current block handles. Current block handles are used to keep track of
|
|
; which handles we are using so that if the out of memory queue is called it won't try to collapse
|
|
; text/rulers for blocks we are in the process of changing!
|
|
|
|
stz err
|
|
stzl W_CurrentBlockHandle
|
|
stzl W_CurrentBlockHandle2
|
|
|
|
; If insertion gap size is zero then simply exit with no error, else we are manipulating the document
|
|
; so go ahead and set file changed bit.
|
|
|
|
lda bytes
|
|
jeq exit
|
|
call D_SetFileChanged,in=(W_CurDoc:l)
|
|
|
|
; Try to make gap in text block {main outer loop}. Get text block for the given paragraph.
|
|
|
|
TryAgain rcall W_GetParRec,in=(par:a),out=(ParPtr:ax)
|
|
movelong [ParPtr],BlockHand
|
|
movelong [BlockHand],BlockPtr
|
|
|
|
; Branch if not enough room exists in the current block to handle the growth. If block is already
|
|
; of StartBlockSize then
|
|
|
|
ldy #W_BUsed
|
|
lda [BlockPtr],y
|
|
sta used
|
|
clc
|
|
adc bytes
|
|
sta newsize
|
|
jcs NoRoom
|
|
cmpw newsize,[BlockPtr]
|
|
bcc IsRoom
|
|
cmpw newsize,#W_StartBlockSize
|
|
jcs NoRoom
|
|
|
|
; Grow the text block to StartBlockSize (obviously it has been collapsed to <4k). Remember the
|
|
; dialog that we are mucking with so that collapse rulers will not try to collapse the text block
|
|
; that we are trying to grow! If we can not grow the text block then try to split it and create a
|
|
; new one. (just like if we couldn't get the room).
|
|
|
|
movelong BlockHand, W_CurrentBlockHandle
|
|
stzl W_CurrentBlockHandle2
|
|
call D_GrowHandle,in=(#0:w,#W_StartBlockSize:w,BlockHand:l),err=err
|
|
jcs NoRoom
|
|
|
|
; Successfully grew the text block - set its new size.
|
|
|
|
movelong [BlockHand],BlockPtr
|
|
moveword #W_StartBlockSize,[BlockPtr]:#W_BSize
|
|
|
|
; Enough room exists in the text block, so make the gap and update used size and other ptrs.
|
|
|
|
IsRoom rcall W_GetAddr,in=(par:a,offset:x)
|
|
|
|
phx ;src high
|
|
pha ;src low
|
|
phx ;dest high
|
|
clc
|
|
adc bytes
|
|
pha ;dest low
|
|
bcc @noinc
|
|
inx
|
|
txa
|
|
sta 3,s ; source & dest now on stack.
|
|
@noinc pea 0 ; length high word - never moving more than 64k
|
|
lda used
|
|
sec
|
|
ldy #W_pOffset
|
|
sbc [ParPtr],y
|
|
sbc offset ; used-(paroffset(inblock)+offset(inpar))
|
|
pha
|
|
_BlockMove ; mem move
|
|
|
|
; Update the used count in the block. Get pointer to last paragraph that needs to be have its ptr
|
|
; updated. While paragraphs left to go and they share the same text block - update paragraph pointers
|
|
; to reflect gap insertion. Exit with error status still clear. - succeeded.
|
|
|
|
moveword newsize,[BlockPtr]:#W_BUsed
|
|
rcall W_GetParRec,in=(W_LastP:a),out=(LastParPtr:ax)
|
|
bra @loopchk
|
|
|
|
@loop cmpl [ParPtr],BlockHand
|
|
bne @endloop
|
|
ldy #W_pOffset
|
|
addword [ParPtr]:y,bytes,[ParPtr]:y
|
|
@loopchk addwl #W_pBytes,ParPtr
|
|
cmpl LastParPtr,ParPtr
|
|
bcs @loop
|
|
@endloop brl exit
|
|
|
|
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
; Either we were unable to grow the paragraph's current text block to allow for the gap size or it
|
|
; was already 4k so we want to perform a split. Three cases exist:
|
|
;
|
|
; 1) Paragraph is already in a block by itself.
|
|
; 2) Paragraph is last paragraph to use the text block we want to split.
|
|
; 3) Paragraph is not last to use text block.
|
|
;
|
|
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
; Check if only paragraph to use text block. If not first paragraph check if previous paragraph had
|
|
; same text block, and if not last paragraph check if next paragraph had same text block.
|
|
|
|
NoRoom movelong [BlockHand],BlockPtr
|
|
cmpw par,#1
|
|
beq @nonebefore
|
|
dec a
|
|
jsl W_GetParRec
|
|
movelong ax,ParPtr
|
|
cmpl [ParPtr],BlockHand
|
|
beq @NotOnly
|
|
|
|
@nonebefore cmpw par,W_LastP
|
|
beq IsOnly
|
|
inc a
|
|
jsl W_GetParRec
|
|
movelong ax,ParPtr
|
|
cmpl [ParPtr],BlockHand
|
|
bne IsOnly
|
|
@NotOnly brl NotAlone
|
|
|
|
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
; CASE 1: Paragraph is already in a block by itself.
|
|
;
|
|
; In this case we grow the text block beyond 4k upto 64k. If text block will exceed 64k then exit
|
|
; with memory error. Make sure to remember text block we are trying to grow so collapse rulers/text
|
|
; in the out of memory queue won't try to shrink what we're growing.
|
|
|
|
IsOnly ldy #W_BUsed
|
|
lda [BlockPtr],y
|
|
clc
|
|
adc bytes
|
|
bcs @gomemerr
|
|
addword newsize,#W_GrowAmount,newmax
|
|
bcs @gomemerr
|
|
stzl W_CurrentBlockHandle2
|
|
movelong BlockHand,W_CurrentBlockHandle
|
|
call D_GrowHandle,in=(#0:w,newmax:w,BlockHand:l)
|
|
bcc @case1ok
|
|
@gomemerr brl domemerr
|
|
|
|
; Succeeded in growing text block so update used and max counts.
|
|
|
|
@case1ok movelong [Blockhand],BlockPtr
|
|
moveword newmax,[BlockPtr] ; update max
|
|
moveword newsize,[BlockPtr]:#W_BUsed ; update used
|
|
|
|
; Enough room exists in the text block, so make the gap and return with error status clear. Restore
|
|
; the paragraph pointer since NoRoom above could have left it pointing to either previous or next
|
|
; paragraph instead.
|
|
|
|
rcall W_GetParRec,in=(par:a),out=(ParPtr:ax)
|
|
rcall W_GetAddr,in=(par:a,offset:x)
|
|
phx ; src high
|
|
pha ; src low
|
|
phx ; dest high
|
|
clc
|
|
adc bytes
|
|
pha ; dest low
|
|
bcc @noinc
|
|
inx
|
|
txa
|
|
sta 3,s
|
|
@noinc pea 0 ; length high word - never more than 64k
|
|
lda used
|
|
sec
|
|
ldy #W_pOffset
|
|
sbc [ParPtr],y
|
|
sbc offset ; used-(paroffset(inblock)+offset(inpar))
|
|
pha
|
|
_BlockMove ; mem move
|
|
brl exit
|
|
|
|
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
; Check if paragraph is last paragraph to use the text block. If is last paragraph in the document
|
|
; then we will need to create a new block for it (don't need to check to see if it will fit in next
|
|
; block - there is none). Addbytes = bytes - (used-offset).
|
|
|
|
NotAlone rcall W_GetParRec,in=(par:a),out=(ParPtr:ax)
|
|
|
|
subword [BlockPtr]:#W_BUsed,[ParPtr]:#W_pOffset,a
|
|
addword a,bytes,addbytes
|
|
|
|
cmpw par,W_LastP
|
|
jeq MakeNewOne
|
|
inc a
|
|
jsl W_GetParRec
|
|
movelong ax,ParPtr2
|
|
|
|
cmpl [ParPtr2],BlockHand
|
|
jeq NotLast
|
|
|
|
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
; CASE 2: Paragraph is last paragraph to use the text block.
|
|
;
|
|
; In this case we need to check to see if the paragraph will fit in the next text block. If not we
|
|
; need to create a new one, else make gap at start of next text block. Update pointers for all other
|
|
; paragraphs using the same text block.
|
|
|
|
IsLast movelong [ParPtr2],BlockHand2
|
|
movelong [BlockHand2],BlockPtr2
|
|
|
|
addword addbytes,[BlockPtr2]:#W_BUsed,a
|
|
cmpw a,[BlockPtr2]:#W_BSize
|
|
jcs MakeNewOne
|
|
|
|
lda par
|
|
inc a
|
|
ldx #0
|
|
jsl W_GetAddr
|
|
phx ;src high
|
|
pha ;src low
|
|
phx ;dest high
|
|
clc
|
|
adc addbytes
|
|
pha ;dest low
|
|
bcc @noinc
|
|
inx
|
|
txa
|
|
sta 3,s
|
|
@noinc pea 0 ; length high word - never more than 64k
|
|
pushword [BlockPtr2]:#W_BUsed
|
|
_BlockMove ;mem move
|
|
|
|
ldy #W_BUsed
|
|
addword addbytes,[BlockPtr2]:y,[BlockPtr2]:y
|
|
|
|
rcall W_GetParRec,in=(W_LastP:a),out=(LastParPtr:ax)
|
|
@loop cmpl [ParPtr2],BlockHand2
|
|
bne @endloop
|
|
ldy #W_pOffset
|
|
addword [ParPtr2]:y,addbytes,[ParPtr2]:y
|
|
addwl #W_pBytes,ParPtr2
|
|
cmpl LastParPtr,ParPtr2
|
|
bcs @loop
|
|
@endloop bra GotRoom
|
|
|
|
; Allocate new text block for the paragraph. Either its the last paragraph in the document or there
|
|
; was not enough room in the text block of the next paragraph after it. If memory error then return
|
|
; it and exit with carry set.
|
|
|
|
MakeNewOne movelong BlockHand,W_CurrentBlockHandle
|
|
stzl W_CurrentBlockHandle2
|
|
call W_MakeEmptyBlock,out=(BlockHand2:l)
|
|
jcs domemerr
|
|
|
|
; If we need more than 4k then we have to resize the empty block we just got. If resize fails or
|
|
; will generate a >64k text block then return with memory error. Note: don't want out of memory
|
|
; queue trying to shrink the handle we're trying to grow! If we can't resize the block make sure
|
|
; we dispose of it.
|
|
|
|
cmpw addbytes,#W_StartBlockSize
|
|
bcc GotRoom
|
|
movelong BlockHand2,W_CurrentBlockHandle
|
|
addword addbytes,#W_GrowAmount,a
|
|
bcs @killblock2
|
|
@growit sta newmax
|
|
pea 0
|
|
pha
|
|
pushlong BlockHand2
|
|
jsl D_GrowHandle
|
|
bcc @gotit
|
|
@killblock2 tool _DisposeHandle,in=(BlockHand2:l)
|
|
brl domemerr
|
|
|
|
; Successfully resized the block - set its max counts. Used is set below.
|
|
|
|
@gotit movelong [BlockHand2],BlockPtr2
|
|
MoveWord newmax,[BlockPtr2]
|
|
|
|
; At this point we can assume that BlockHand2 can contain the given paragraph. Move all the text
|
|
; for the paragraph before where we want the gap into our new text block.
|
|
|
|
GotRoom addlong [BlockHand2],#W_BHeader,LastParPtr
|
|
rcall W_GetAddr,in=(par:a,#0:x)
|
|
phx ; src high
|
|
pha ; src low
|
|
pushlong LastParPtr
|
|
pushword #0 ; high, never moving more than 64k
|
|
pushword offset
|
|
_BlockMove ; mem move
|
|
|
|
; Get the total number of bytes that existed in the paragraph before growing it. Move text up
|
|
; to create the gap.
|
|
|
|
subword addbytes,bytes,addbytes
|
|
rcall W_GetAddr,in=(par:a,offset:x)
|
|
phx ; src high
|
|
pha ; src low
|
|
addword bytes,offset,a
|
|
addwl a,LastParPtr
|
|
pushlong LastParPtr
|
|
pushword #0 ; high, never moving more than 64k
|
|
subword addbytes,offset,s
|
|
_BlockMove ; mem move
|
|
|
|
; Update used counts for both original text block and new text block. Subtract the total number of
|
|
; bytes in the paragraph from the first block used count and add bytes grown to second block count.
|
|
; Replace text block for paragraph with the new one we have created. Exit with no errors.
|
|
|
|
movelong [ParPtr],BlockHand
|
|
movelong [BlockHand],BlockPtr
|
|
movelong [BlockHand2],BlockPtr2
|
|
|
|
ldy #W_BUsed
|
|
subword [BlockPtr]:y,addbytes,[BlockPtr]:y
|
|
addword bytes,addbytes,a
|
|
addword a,[BlockPtr2]:y,[BlockPtr2]:y
|
|
|
|
movelong BlockHand2,[ParPtr]
|
|
moveword #W_BHeader,[ParPtr]:#W_pOffset
|
|
brl exit
|
|
|
|
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
; CASE 3: Paragraph is not last to use text block.
|
|
;
|
|
; In this case we need to put all the paragraphs after this one in their own block and then call
|
|
; MakeRoom to make this paragraph as big as we can.
|
|
|
|
; Get pointers to last document paragraph and next paragraph.
|
|
|
|
NotLast rcall W_GetParRec,in=(W_LastP:a),out=(LastParPtr:ax)
|
|
lda par
|
|
inc a
|
|
sta CurPar
|
|
jsl W_GetParRec
|
|
movelong ax,ParPtr
|
|
movelong ax,ParPtr2
|
|
|
|
; Get amount of space taken up by all latter paragraphs that share the same text block. Then find
|
|
; the last paragraph that shares the same text block with the paragraph we're trying to grow. If
|
|
; all remaining paragraphs in the document share this text block then we will need to create a
|
|
; brand new text block.
|
|
|
|
subword [BlockPtr]:#W_BUsed,[ParPtr]:#W_pOffset,addbytes
|
|
|
|
@loop cmpl [ParPtr2],BlockHand
|
|
bne GotIt
|
|
inc CurPar
|
|
addwl #W_pBytes,ParPtr2
|
|
cmpl LastParPtr,ParPtr2
|
|
bcs @loop
|
|
brl MakeNewOne2
|
|
|
|
; ParPtr2 now points to first paragraph with a different text block. Get its text block pointer.
|
|
|
|
GotIt movelong [ParPtr2],BlockHand2
|
|
movelong [BlockHand2],BlockPtr2
|
|
|
|
; Check if the text block can contain the latter paragraphs. If not we will need to create a brand
|
|
; new text block to hold them.
|
|
|
|
addword addbytes,[BlockPtr2]:#W_BUsed,a
|
|
cmpw a,[BlockPtr2]:#W_BSize
|
|
jcs MakeNewOne2
|
|
|
|
; Enough memory exists in the next text block to hold the paragraphs we are bumping. So move the next
|
|
; text blocks contents to make room for inserting the text we are bumping.
|
|
|
|
lda Curpar
|
|
ldx #0
|
|
jsl W_GetAddr
|
|
phx ; src high
|
|
pha ; src low
|
|
phx ; dest high
|
|
clc
|
|
adc addbytes
|
|
pha ; dest low
|
|
bcc @noinc
|
|
inx
|
|
txa
|
|
sta 3,s
|
|
@noinc pea 0 ; length high word - never more than 64k
|
|
subword [BlockPtr2]:#W_BUsed,#W_BHeader,s
|
|
_BlockMove ; mem move
|
|
|
|
; Update all the pointers for the paragraphs which reference the text block we just made a gap in.
|
|
; ParPtr2 initially points to curpars text block.
|
|
|
|
rcall W_GetParRec,in=(W_LastP:a),out=(LastParPtr:ax)
|
|
@loop cmpl [ParPtr2],BlockHand2
|
|
jne GotRoom2
|
|
ldy #W_pOffset
|
|
addword [ParPtr2]:y,addbytes,[ParPtr2]:y
|
|
addwl #W_pBytes,ParPtr2
|
|
cmpl LastParPtr,ParPtr2
|
|
bcs @loop
|
|
bra GotRoom2
|
|
|
|
; Need to create a new text block to hold the paragraphs that come after the one that we are trying
|
|
; to place a gap in (so it will have the text block to itself). If we get memory error then return
|
|
; it to the caller.
|
|
|
|
MakeNewOne2 movelong BlockHand, W_CurrentBlockHandle
|
|
stzl W_CurrentBlockHandle2
|
|
call W_MakeEmptyBlock,out=(BlockHand2:l)
|
|
jcs domemerr
|
|
|
|
; If we need more than 4k then we have to resize the empty block we just got. If resize fails or
|
|
; will generate a >64k text block then return with memory error. Note: don't want out of memory
|
|
; queue trying to shrink the handle we're trying to grow! If we can't resize the block make sure
|
|
; we dispose of it.
|
|
|
|
cmpw addbytes,#W_StartBlockSize
|
|
bcc GotRoom2
|
|
movelong BlockHand2,W_CurrentBlockHandle
|
|
addword addbytes,#W_GrowAmount,a
|
|
bcs @killblock2
|
|
@growit pea 0
|
|
pha
|
|
pushlong BlockHand2
|
|
jsl D_GrowHandle
|
|
bcc @gotit
|
|
@killblock2 tool _DisposeHandle,in=(BlockHand2:l)
|
|
brl domemerr
|
|
|
|
; Successfully resized the block - set its used and max counts.
|
|
|
|
@gotit movelong [BlockHand2],BlockPtr2
|
|
moveword addbytes,[BlockPtr2]:#W_BUsed
|
|
addword a,#W_GrowAmount,[BlockPtr2]
|
|
|
|
; We can assume at this point that BlockHand2 can contain the paragraphs after par. Move the text for
|
|
; these paragraphs into BlockHand2. Addbytes = amount of text that needs to be moved.
|
|
|
|
GotRoom2 lda par
|
|
inc a
|
|
jsl W_GetParRec
|
|
movelong ax,ParPtr
|
|
|
|
movelong [ParPtr],BlockHand
|
|
movelong [BlockHand],BlockPtr
|
|
addlong [BlockHand2],#W_BHeader,LastParPtr
|
|
|
|
lda par
|
|
inc a
|
|
ldx #0
|
|
jsl W_GetAddr
|
|
phx ; src high
|
|
pha ; src low
|
|
pushlong LastParPtr
|
|
pushword #0 ; high, never moving more than 64k
|
|
pushword addbytes
|
|
_BlockMove ; mem move
|
|
|
|
; Remove bytes from original text block used count and add to BlockHand2 used count.
|
|
|
|
movelong [Blockhand2],BlockPtr2
|
|
ldy #W_BUsed
|
|
subword [BlockPtr]:y,addbytes,[BlockPtr]:y
|
|
addword [BlockPtr2]:y,addbytes,[BlockPtr2]:y
|
|
|
|
; Get pointer to first paragraph that differed in text block ( or past last paragraph in document ).
|
|
; Get negative offset for paragraph's into new text block. For all paragraphs that came after par
|
|
; originally and are now in their own text block update their offsets. We have successfully
|
|
; split the block - now try to grow par's text block to the correct size.
|
|
|
|
rcall W_GetParRec,in=(CurPar:a),out=(LastParPtr:ax)
|
|
subword #W_BHeader,[ParPtr]:#W_pOffset,addbytes
|
|
|
|
@loop ldy #W_pOffset
|
|
addword [ParPtr]:y,addbytes,[ParPtr]:y
|
|
movelong BlockHand2,[ParPtr]
|
|
addwl #W_pBytes,ParPtr
|
|
cmpl ParPtr,LastParPtr
|
|
bcc @loop
|
|
brl TryAgain
|
|
|
|
domemerr moveword #$201,err
|
|
exit stzl W_CurrentBlockHandle
|
|
stzl W_CurrentBlockHandle2
|
|
return
|
|
|
|
W_CurrentBlockHandle DS.L 1
|
|
W_CurrentBlockHandle2 DS.L 1
|
|
|
|
ENDP
|
|
|
|
*****************************************************************************************************
|
|
; W_LessRoom ( Paragraph:word, Offset:word, Bytes:word )
|
|
;
|
|
; This routine is called to remove the given number of bytes at the given offset in the given
|
|
; paragraph's text block.
|
|
;
|
|
; Note: Always returns with no error (carry clear).
|
|
|
|
W_LessRoom PROC EXPORT
|
|
;Using wpglobals
|
|
;Using W_ParData
|
|
|
|
input par:w,offset:w,bytes:w
|
|
local BlockPtr:l,BlockHand:l,newsize:w,ParPtr:l,LastParPtr:l
|
|
local used:w,temp:l,ParOffset:w
|
|
error err
|
|
begin
|
|
|
|
; Deleting text so set file changed status. Get pointer to text block for paragraph.
|
|
|
|
stz err
|
|
call D_SetFileChanged,in=(W_CurDoc:l)
|
|
rcall W_GetParRec,in=(par:a),out=(ParPtr:ax)
|
|
movelong [ParPtr],BlockHand
|
|
moveword [ParPtr]:#W_pOffset,ParOffset
|
|
movelong [BlockHand],BlockPtr
|
|
|
|
; Subtract bytes from used count for text block.
|
|
|
|
ldy #W_BUsed
|
|
lda [BlockPtr],y
|
|
sta used
|
|
sec
|
|
sbc bytes
|
|
sta newsize
|
|
|
|
rcall W_GetAddr,in=(par:a,offset:x),out=(temp:ax)
|
|
clc
|
|
adc bytes
|
|
bcc @noinc
|
|
inx
|
|
@noinc phx ; source
|
|
pha
|
|
pushlong temp ; dest
|
|
pushword #0 ; high, never moving more than 64k
|
|
lda used
|
|
sec
|
|
sbc offset
|
|
sbc bytes
|
|
sbc ParOffset
|
|
pha
|
|
_BlockMove ; mem move
|
|
|
|
; Update used count in text block.
|
|
|
|
moveword newsize,[BlockPtr]:#W_BUsed
|
|
|
|
; Update all paragraph offsets for latter paragraphs that share the same text block.
|
|
|
|
rcall W_GetParRec,in=(W_LastP:a),out=(LastParPtr:ax)
|
|
bra @check
|
|
|
|
@loop cmpl [ParPtr],BlockHand
|
|
bne @endloop
|
|
ldy #W_pOffset
|
|
subword [ParPtr]:y,bytes,[ParPtr]:y
|
|
@check addwl #W_pBytes,ParPtr
|
|
cmpl LastParPtr,ParPtr
|
|
bcs @loop
|
|
@endloop
|
|
|
|
exit return
|
|
|
|
ENDP
|
|
|
|
*****************************************************************************************************
|
|
; W_NewRuler ( ): RulerHandle:long
|
|
;
|
|
; This routine is called to allocate a new standard ruler and initialize its used count to zero.
|
|
;
|
|
; Note: can return memory errors.
|
|
|
|
W_NewRuler PROC EXPORT
|
|
;Using W_RulerData
|
|
;Using WPGlobals
|
|
|
|
output DogRuler:l
|
|
local ptr:l
|
|
error err
|
|
begin
|
|
|
|
call D_NeedHand,in=(#W_RulBytes:l),out=(DogRuler:l),err=err
|
|
bcs @exit
|
|
tool _PtrToHand,in=(#StdRuler:l,DogRuler:l,#W_RulBytes:l)
|
|
movelong [DogRuler],ptr
|
|
moveword #0,[ptr]
|
|
|
|
@exit return
|
|
|
|
ENDP
|
|
|
|
*****************************************************************************************************
|
|
; W_ReadRuler ( RulerHandle:ax )
|
|
;
|
|
; This routine is called to move the given ruler's information into the WP current ruler globals.
|
|
|
|
W_ReadRuler PROC EXPORT
|
|
;Using WPGlobals
|
|
|
|
tool _HandToPtr,in=(ax:l,#W_WPRuler:l,#W_RulBytes:l)
|
|
rtl
|
|
|
|
ENDP
|
|
|
|
*****************************************************************************************************
|
|
; W_ReadRulerP ( ParagraphPtr:ax )
|
|
;
|
|
; This routine is called to move the given paragraph's ruler information into the WP current
|
|
; ruler globals.
|
|
|
|
W_ReadRulerP PROC EXPORT
|
|
;Using D_GlobalData
|
|
;Using WPGlobals
|
|
|
|
ParRec equ 0
|
|
|
|
tay
|
|
phd
|
|
lda >D_MainZPage
|
|
tcd
|
|
sty ParRec
|
|
stx ParRec+2
|
|
ldy #W_pRulerHand+2
|
|
lda [ParRec],y
|
|
tax
|
|
ldy #W_pRulerHand
|
|
lda [ParRec],y
|
|
jsl W_ReadRuler
|
|
pld
|
|
rtl
|
|
|
|
ENDP
|
|
|
|
*****************************************************************************************************
|
|
; W_UseRuler ( Count:word, RulerHand:long )
|
|
;
|
|
; This routine is called to increment the ruler's used count. This routine should be called
|
|
; whenever a paragraph is using the ruler.
|
|
|
|
W_UseRuler PROC EXPORT
|
|
|
|
input times:w,ruler:l
|
|
local ptr:l
|
|
begin
|
|
|
|
movelong [ruler],ptr
|
|
addword times,[ptr],[ptr]
|
|
|
|
return
|
|
|
|
ENDP
|
|
|
|
*****************************************************************************************************
|
|
; W_UnUseRuler ( Count:word, RulerHand:long )
|
|
;
|
|
; This routine is called to decrement the ruler's used count. This routine should be called
|
|
; whenever a paragraph is no longer using a ruler.
|
|
|
|
W_UnUseRuler PROC EXPORT
|
|
input times:w,ruler:l
|
|
local ptr:l
|
|
begin
|
|
|
|
movelong [ruler],ptr
|
|
subword [ptr],times,[ptr]
|
|
beq @killit
|
|
bpl @exit
|
|
@killit tool _DisposeHandle,in=(ruler:l)
|
|
|
|
@exit return
|
|
|
|
ENDP
|
|
|
|
*****************************************************************************************************
|
|
; W_FindLine ( Paragraph:word, Offset:word ): Line:word
|
|
;
|
|
; This routine is called to return the line in the paragraph corresponding to the given offset
|
|
; into the paragraph.
|
|
|
|
W_FindLine PROC EXPORT
|
|
|
|
input par:w,offset:w
|
|
local handle:l,ptr:l,ParRec:l,LinePtr:l,Ptr2:l
|
|
output line:w
|
|
begin
|
|
|
|
; Get line handle for paragraph. If no line handle exits then create valid line handles for the
|
|
; paragraph. If we can't make lines for paragraph then return with line set to last line and hope
|
|
; it's good enough.
|
|
|
|
rcall W_GetParRec,in=(par:a),out=(ParRec:ax)
|
|
movelong [ParRec]:#W_pLineHand,handle
|
|
cpzl handle
|
|
bne @notNIL
|
|
|
|
@makelines call W_ValidLines,in=(par:w)
|
|
bcc @gotlines
|
|
moveword [ParRec]:#W_pLastLine,line
|
|
dec line
|
|
brl exit
|
|
|
|
; If line handle has been purged then try to make lines.
|
|
|
|
@gotlines movelong [ParRec]:#W_pLineHand,handle
|
|
@notNIL movelong [handle],ptr
|
|
cpzl ptr
|
|
beq @makelines
|
|
|
|
; Loop through all lines for the paragraph comparing the given offset against them to determine in
|
|
; which line the offset falls.
|
|
|
|
stz line
|
|
@loop inc line
|
|
rcall W_GetLineRec,in=(ptr:ax,line:y),out=(lineptr:ax)
|
|
|
|
cmpw offset,[LinePtr]:#W_lOffset
|
|
beq @checktab
|
|
bcs @loop
|
|
bra @foundline
|
|
|
|
@checktab rcall W_GetAddr,in=(par:a,offset:x),out=(ptr2:ax)
|
|
cmpb [Ptr2],#9
|
|
bne @loop
|
|
|
|
@foundline dec line
|
|
cmpw [ParRec]:#W_pLastLine,line
|
|
beq @skip2
|
|
bcs exit
|
|
|
|
@skip2 dec a
|
|
sta line
|
|
|
|
exit return
|
|
|
|
ENDP
|
|
|
|
*****************************************************************************************************
|
|
; W_MakeCR ( Paragraph:word, Line:word, Offset:word )
|
|
;
|
|
; This routine is called to add a carriage return at the given offset in the given paragraph/line.
|
|
; This will create a new paragraph. The method used to insert the paragraph is as follows:
|
|
;
|
|
; 1. Get current font information
|
|
; 2. MakeRoom in paragraph at the given offset to insert a new text header + 1 carriage return char.
|
|
; 3. Put the current font information into the gap we made.
|
|
; 4. Make a new paragraph entry after the given paragraph.
|
|
; 5. Setup the new paragraph's offset.
|
|
; 6. MakeLines for both new paragraphs.
|
|
;
|
|
; Note: This routine can return memory errors.
|
|
|
|
W_MakeCr PROC EXPORT
|
|
;Using wpglobals
|
|
;Using W_ParData
|
|
|
|
input par:w,line:w,offset:w
|
|
local font:w,style:w,color:w,ptr:l,ParRec:l
|
|
local ParRec2:l
|
|
error err
|
|
begin
|
|
|
|
; Determine current font information at place we want to insert CR. Make room for new carriage return
|
|
; and text header in text block. If memory error then exit with error.
|
|
|
|
call W_FindFont,in=(par:w,line:w,offset:w),out=(style:w,font:w,color:w)
|
|
call W_MakeRoom,in=(par:w,offset:w,#W_TextHeader+1:w),err=err
|
|
bcs @goexit
|
|
|
|
; Made the gap. Now want to make sure we will be able to grow the paragraph array. Try to create new
|
|
; paragraph entry. If we can't then remove the gap and return with a memory error.
|
|
|
|
call W_MakeNewParRec,in=(par:w),err=err
|
|
bcc @gotpar
|
|
call W_LessRoom,in=(par:w,offset:w,#W_TextHeader+1:w)
|
|
@goexit brl exit
|
|
|
|
; Now get pointer to where we want CR and text header to start. Insert CR and text header.
|
|
|
|
@gotpar rcall W_GetAddr,in=(par:a,offset:x),out=(ptr:ax)
|
|
moveword #cr,[ptr]
|
|
moveword font,[ptr]:#1
|
|
moveword style,[ptr]:#3
|
|
moveword color,[ptr]:#5
|
|
|
|
; Get pointers to par and new par we added.
|
|
|
|
rcall W_GetParRec,in=(par:a),out=(ParRec:ax)
|
|
lda par
|
|
inc a
|
|
jsl W_GetParRec
|
|
movelong ax,ParRec2
|
|
|
|
; New paragraph's offset is going to be 1 past the CR we inserted @ offset in par.
|
|
|
|
moveword [ParRec]:#W_pOffset,a
|
|
sec ; inc 1 past the cr
|
|
adc offset
|
|
sta [ParRec2],y
|
|
|
|
; Make lines for old and new paragraphs.
|
|
|
|
call W_MakeLines,in=(par:w)
|
|
lda par
|
|
inc a
|
|
pha
|
|
jsl W_MakeLines
|
|
|
|
exit return
|
|
|
|
ENDP
|
|
|
|
*****************************************************************************************************
|
|
; W_MakeNewParRec ( Paragraph:word )
|
|
;
|
|
; This routine is called to create a new paragraph record in the paragraph array - after the given
|
|
; paragraph. The new paragraph entry is initialized as follows:
|
|
;
|
|
; TextBlock - same as Paragraph
|
|
; offset - ???
|
|
; Attr - 0
|
|
; RulerHandle - same as Paragraph
|
|
; Pixels - 0
|
|
; LineHandle - NIL
|
|
; LastLine - 0
|
|
;
|
|
; Note: Memory errors are returned!
|
|
|
|
W_MakeNewParRec PROC EXPORT
|
|
;Using wpglobals
|
|
|
|
ParIncment equ 10
|
|
|
|
input par:w
|
|
local Src:l,Dest:l,Length:l,NewMax:w,NewSize:l
|
|
error err
|
|
begin
|
|
|
|
; Check if paragraph array has enough room to just add entry. If not try to grow paragraph array to
|
|
; new size. If memory error then exit with error globals intact; else update W_MaxP.
|
|
|
|
stz err
|
|
cmpw W_LastP,W_MaxP
|
|
bcc @hasroom
|
|
adc #ParIncment-1
|
|
sta NewMax
|
|
|
|
tool _Multiply,in=(NewMax:w,#W_pBytes:w),out=(NewSize:l)
|
|
call D_GrowLHandle,in=(NewSize:l,W_PHandle:l),out=(W_PPtr:l),err=err
|
|
jcs exit
|
|
moveword NewMax,W_MaxP
|
|
|
|
; Enough room now exists in paragraph array handle to add extra paragraph entry. Get pointers to
|
|
; par and par+1. Copy par through last par contents up one paragraph entry.
|
|
|
|
@hasroom rcall W_GetParRec,in=(par:a),out=(src:ax)
|
|
lda par
|
|
inc a
|
|
jsl W_GetParRec
|
|
movelong ax,Dest
|
|
|
|
inc W_LastP
|
|
rcall W_GetParRec,in=(W_LastP:a),out=(length:ax)
|
|
cmpw par,W_LastP
|
|
beq @nomove
|
|
|
|
pushlong Src
|
|
pushlong Dest
|
|
sublong Length,Src,s
|
|
_BlockMove
|
|
|
|
; Initialize other fields of new paragraph record. Note: TextBlock and RulerHandles will have been
|
|
; inherited by the copy.
|
|
|
|
@nomove lda #0
|
|
moveword a,[Dest]:#W_pAttr
|
|
moveword a,[Dest]:#W_pLastLine
|
|
moveword a,[Dest]:#W_pPixels
|
|
moveword a,[Dest]:#W_pLineHand
|
|
moveword a,[Dest]:#W_pLineHand+2
|
|
call W_UseRuler,in=(#1:w,[Dest]:#W_pRulerHand:l)
|
|
|
|
exit return
|
|
|
|
ENDP
|
|
|
|
*****************************************************************************************************
|
|
; W_ParLock ( Paragraph:word )
|
|
;
|
|
; This routine is called to lock the text block and line handles for the given paragraph.
|
|
|
|
W_ParLock PROC EXPORT
|
|
|
|
input par:w
|
|
local ParRec:l
|
|
begin
|
|
|
|
rcall W_GetParRec,in=(par:a),out=(ParRec:ax)
|
|
tool _HLock,in=([ParRec]:#W_pBlockHand:l)
|
|
tool _HLock,in=([ParRec]:#W_pLineHand:l)
|
|
|
|
return
|
|
|
|
ENDP
|
|
|
|
*****************************************************************************************************
|
|
; W_ParUnLock ( Paragraph:word )
|
|
;
|
|
; This routine is called to unlock the text block and line handles for the given paragraph.
|
|
|
|
W_ParUnLock PROC EXPORT
|
|
|
|
input par:w
|
|
local ParRec:l
|
|
begin
|
|
|
|
rcall W_GetParRec,in=(par:a),out=(ParRec:ax)
|
|
tool _HUnLock,in=([ParRec]:#W_pBlockHand:l)
|
|
tool _HUnLock,in=([ParRec]:#W_pLineHand:l)
|
|
|
|
return
|
|
|
|
ENDP
|
|
|
|
*****************************************************************************************************
|
|
; W_GetLastLine ( Paragraph:a ):Line:a
|
|
;
|
|
; This routine is called to return the last line for the given paragraph.
|
|
|
|
W_GetLastLine PROC EXPORT
|
|
|
|
pha
|
|
pha
|
|
pha
|
|
jsl W_GetLastLGuts
|
|
plx
|
|
pla
|
|
rtl
|
|
|
|
ENDP
|
|
|
|
*****************************************************************************************************
|
|
; W_GetLastLGuts ( Paragraph:word ): Line:word, Offset:word
|
|
;
|
|
; This routine is called to return the last line for the given paragraph and its offset in the
|
|
; paragraph's text block.
|
|
|
|
W_GetLastLGuts PROC EXPORT
|
|
;Using wpglobals
|
|
;Using D_GlobalData
|
|
|
|
input par:w
|
|
output line:w,offset:w
|
|
local ptr:l,LinePtr:l
|
|
begin
|
|
|
|
rcall W_GetParRec,in=(Par:a),out=(Ptr:ax)
|
|
moveword [ptr]:#W_pLastLine,line
|
|
call W_GetLRecPtr,in=(par:w,line:w),out=(lineptr:l)
|
|
moveword [LinePtr]:#W_lOffset,offset
|
|
dec line
|
|
|
|
return
|
|
|
|
ENDP
|
|
|
|
*****************************************************************************************************
|
|
; W_GetEndPar ( Paragraph:word ): Bytes:word
|
|
;
|
|
; This routine is called to return the number of bytes in the given paragraph.
|
|
|
|
W_GetEndPar PROC EXPORT
|
|
;Using wpglobals
|
|
|
|
input par:w
|
|
local ParRec:l,Block:l,ptr:l
|
|
output bytes:w
|
|
begin
|
|
|
|
rcall W_GetParRec,in=(par:a),out=(parrec:ax)
|
|
movelong [ParRec],Block
|
|
movelong [Block],ptr
|
|
moveword [ptr]:#W_BUsed,bytes
|
|
|
|
cmpw par,W_LastP
|
|
bcs @GotBytes
|
|
cmpl [ParRec],[ParRec]:#W_pBytes
|
|
bne @GotBytes
|
|
moveword [ParRec]:#W_pOffset+W_pBytes,bytes
|
|
|
|
@GotBytes subword bytes,[ParRec]:#W_pOffset,bytes
|
|
dec bytes
|
|
|
|
return
|
|
|
|
ENDP
|
|
|
|
*****************************************************************************************************
|
|
; W_DelPars ( Par1:word, Par2:word )
|
|
;
|
|
; This routine is called to delete the range of paragraphs between 1 & 2 inclusive.
|
|
|
|
W_DelPars PROC EXPORT
|
|
;Using wpglobals
|
|
|
|
input par1:w,par2:w
|
|
local EndPtr:l,EP1Ptr:l,bytes:l,Pm1Ptr:l,CurPar:l,BPtr:l
|
|
local FirstBlock:l,LastBlock:l,OldBlock:l,ParRec:l
|
|
local ptr:l,BegOffset:w,EndOffset:w,LastParPtr:l
|
|
begin
|
|
|
|
; Lock down paragraph array handle and get pointer to its end.
|
|
|
|
rcall D_Deref,in=(W_PHandle:ax)
|
|
lda W_LastP
|
|
inc a
|
|
jsl W_GetParRec
|
|
movelong ax,EndPtr
|
|
|
|
; Get pointers to paragraph before par1 and paragraph after par2.
|
|
|
|
lda par1
|
|
dec a
|
|
jsl W_GetParRec
|
|
movelong ax,Pm1Ptr
|
|
|
|
lda par2
|
|
inc a
|
|
jsl W_GetParRec
|
|
movelong ax,EP1Ptr
|
|
|
|
; Initialize first and last text blocks for loop.
|
|
|
|
movelong [Pm1Ptr],FirstBlock
|
|
stzl LastBlock
|
|
cmpw W_LastP,par2
|
|
beq @GotLast
|
|
movelong [EP1Ptr],LastBlock
|
|
|
|
@GotLast moveword par1,CurPar
|
|
stzl OldBlock
|
|
|
|
PLoop rcall W_GetParRec,in=(CurPar:a),out=(ParRec:ax)
|
|
cmpw [ParRec]:#W_pAttr,#W_PgBrk
|
|
beq NextPar
|
|
|
|
call W_UnUseRuler,in=(#1:w,[ParRec]:#W_pRulerHand:l)
|
|
cpzl [ParRec]:#W_pLineHand
|
|
beq NoKill
|
|
tool _DisposeHandle,in=([ParRec]:#W_pLineHand:l)
|
|
|
|
NoKill cmpl [ParRec],OldBlock
|
|
beq NextPar
|
|
movelong [ParRec],OldBlock
|
|
cmpl OldBlock,FirstBlock
|
|
beq NextPar
|
|
cmpl OldBlock,LastBlock
|
|
beq NextPar
|
|
tool _DisposeHandle,in=(OldBlock:l)
|
|
|
|
NextPar inc CurPar
|
|
cmpw par2,CurPar
|
|
jge PLoop
|
|
|
|
; now am done with all the in between pars, work on extremes
|
|
|
|
movelong [FirstBlock],BPtr
|
|
cmpl FirstBlock,LastBlock
|
|
bne NotSame
|
|
|
|
moveword [EP1Ptr]:#W_pOffset,EndOffset
|
|
moveword [PM1Ptr]:#W_pBytes+W_pOffset,BegOffset
|
|
bra GotBOffset
|
|
|
|
NotSame cmpl [PM1Ptr],[PM1Ptr]:#W_pBytes
|
|
bne NoZap
|
|
moveword [PM1Ptr]:#W_pBytes+W_pOffset,[BPtr]:#W_BUsed
|
|
|
|
NoZap moveword #W_BHeader,BegOffset
|
|
cpzl LastBlock
|
|
jeq NoMove
|
|
rcall W_GetParRec,in=(par2:a),out=(parrec:ax)
|
|
cmpl [ParRec],[EP1Ptr]
|
|
jne DoArray
|
|
movelong [LastBlock],BPtr
|
|
moveword [EP1Ptr]:#W_pOffset,EndOffset
|
|
|
|
GotBOffset ldx BPtr+2
|
|
addword EndOffset,Bptr,a
|
|
bcc NoIx
|
|
inx
|
|
NoIX phx
|
|
pha
|
|
ldx BPtr+2
|
|
addword BegOffset,Bptr,a
|
|
bcc NoIx2
|
|
inx
|
|
NoIX2 phx
|
|
pha
|
|
pushword #0
|
|
subword [Bptr]:#W_BUsed,EndOffset,s
|
|
_BlockMove
|
|
|
|
subword EndOffset,BegOffset,bytes
|
|
subword [BPtr]:#W_BUsed,bytes,[BPtr]:#W_BUsed
|
|
movelong EP1Ptr,ParRec
|
|
|
|
; Now update all relevant ptrs.
|
|
|
|
rcall W_GetParRec,in=(W_LastP:a),out=(LastParPtr:ax)
|
|
bra @check
|
|
@loop cmpl [ParRec],LastBlock
|
|
bne @endloop
|
|
|
|
ldy #W_pOffset
|
|
subword [ParRec]:y,bytes,[ParRec]:y
|
|
addwl #W_pBytes,ParRec
|
|
@check cmpl LastParPtr,ParRec
|
|
bge @loop
|
|
@endloop
|
|
|
|
; Now adjust the par array
|
|
|
|
DoArray sublong EndPtr,EP1Ptr,bytes
|
|
|
|
pushlong EP1Ptr
|
|
lda par1
|
|
jsl W_GetParRec
|
|
phx
|
|
pha
|
|
pushlong bytes
|
|
_BlockMove
|
|
|
|
; W_LastP - (par2-par1+1)
|
|
|
|
NoMove lda W_LastP
|
|
clc
|
|
sbc par2
|
|
clc
|
|
adc par1
|
|
sta W_LastP
|
|
|
|
return
|
|
|
|
ENDP
|
|
|
|
|
|
*****************************************************************************************************
|
|
; W_CheckWidow ( Paragraph:a )
|
|
;
|
|
; This routine is called to check if the given paragraph can be widowed or not. The carry will be
|
|
; set on return if widow is set in the ruler bits of the paragraph's ruler.
|
|
|
|
W_CheckWidow PROC EXPORT
|
|
;Using wpglobals
|
|
;Using D_GlobalData
|
|
|
|
handle equ 0
|
|
ptr equ 4
|
|
|
|
tay
|
|
phd
|
|
lda >D_MainZPage
|
|
tcd
|
|
clc
|
|
lda W_Stuff
|
|
bne @exit
|
|
|
|
tya
|
|
jsl W_GetParRec
|
|
jsl W_ReadRulerP
|
|
|
|
lda W_RulBits
|
|
and #W_r_widow
|
|
clc
|
|
beq @exit
|
|
sec
|
|
@exit pld
|
|
rtl
|
|
|
|
ENDP
|
|
END
|
|
|