antoine-source/appleworksgs/Scrap/Src/wpdisk.aii
2023-03-04 03:45:20 +01:00

1 line
15 KiB
Plaintext
Executable File

*****************************************************************************************************
* WP File I/O Routines
*
* This file contains the routines used to read and write WP scraps & PL text threads.
*
*****************************************************************************************************
load 'macros.dump'
include 'driver.equ'
include 'scrap.equ'
IMPORT D_AlertBox
IMPORT D_BeachBall
IMPORT D_CurCursor
IMPORT D_Deref
IMPORT D_NeedHandle
IMPORT D_Read2
IMPORT D_ReadHandle2
IMPORT D_SetCursor
IMPORT D_WriteHandle2
IMPORT D_MustHandle
IMPORT D_Write2
IMPORT D_SetMark2
IMPORT X_DisposeWPScrap
IMPORT X_MassageWPScrap
IMPORT X_OldCursor
IMPORT X_ParBlockSize
IMPORT X_ReadWPScrap
IMPORT X_RulerSize
IMPORT X_WriteThread
*****************************************************************************************************
; X_ScReadWPScrap ( FileRef:word, Type:word )
;
; This routine is called to read both WPScraps and PL text threads from disk. If Type is non-zero
; then read text thread else read WPscrap. FileRef should be the file reference to the already opened
; and correctly positioned file. Memory and disk errors are returned.
;
; It is assumed that the bank has already been set to the Scrap segments bank.
X_ScReadWPScrap PROC EXPORT
;Using X_WPScrapData
;Using X_WPFileData
;Using D_IOData
;Using X_ClipData
;Using D_CursorData
input FileRef:w,Type:w
local Bpars:w,SaveArraySize:l,SaveArrayHand:l,SAPtr:l
local Blocks:w,Rulers:w,Picts:w
local BListhand:l,BLPtr:l,RListHand:l,RLPtr:l,PListHand:l,PLPtr:l
local Block:l,Ruler:l,ScrapSize:l,ScrapPtr:l,RulerPtr:l
local PBlockSize:w,Scratch:l
local Handles:w,RHands:w,BHands:w
output Scrap:l
error err
begin
; Save the current cursor and put up the beachball cursor.
moveword >D_CurCursor,X_OldCursor
jsl D_Beachball
; Set PBlockSize depending on whether we are reading in a PL text thread or a WP scrap.
lda Type
bne notwp
moveword #X_ParBlockSize,PBlockSize
bra cont
notwp moveword #(X_ParBlockSize+4),PBlockSize
; Read in the # of paragraph blocks in the file. Use this count to create temporary array into which
; we will read the paragraph info. Create the handle for the scrap we will be filling in with the
; information we read from disk. If any memory or disk errors occur dispose of the memory we have
; allocated and exit.
cont call D_Read2,in=(FileRef:w,!Bpars:l,#2:l),out=(ax:l),err=err
jcs exit
tool _Multiply,in=(BPars:w,#12:w),out=(SaveArraySize:l)
call D_NeedHandle,in=(SaveArraySize:l,#$8000:w),out=(SaveArrayHand:l),err=err
jcs exit
movelong [SaveArrayHand],SAPtr
call D_Read2,in=(FileRef:w,SAPtr:l,SaveArraySize:l),out=(ax:l),err=err
jcs killsave
tool _Multiply,in=(Bpars:w,PBlockSize:w),out=(ScrapSize:l)
addlong ScrapSize,#2,ScrapSize
call D_NeedHandle,in=(ScrapSize:l,#$8000:w),out=(Scrap:l),err=err
jcs killsave
; Put the number of paragraphs into the first word of the scrap, then bump scrapptr past the
; paragraph count. Initialize the number of text blocks & rulers to zero.
movelong [Scrap],ScrapPtr
moveword BPars,[ScrapPtr]
addlong ScrapPtr,#2,ScrapPtr
stz Blocks
stz Rulers
stz Picts
; For all paragraph blocks do: copy paragraph info to the scrap; keep track of number of rulers and
; text blocks encountered.
parloop lda Bpars
jeq doneloop
textblock cmpw [SAPtr],Blocks
blt nonewblock
inc Blocks
nonewblock lda Type
bne realruler
ldy #4
lda [SAPtr],y
bne incloop
realruler cmpw [SAPtr]:#6,Rulers
blt incloop
inc Rulers
incloop moveword [SAPtr]:#2,[ScrapPtr]:#X_scpOffset
moveword [SAPtr]:#4,[ScrapPtr]:#X_scpAttr
moveword [SAPtr]:#8,[ScrapPtr]:#X_scpPixels
moveword [SAPtr]:#10,[ScrapPtr]:#X_scpLastLine
movelong #0,[ScrapPtr]:#X_scpLinehand
addlong SAPtr,#12,SAPtr
addwl PBlockSize,ScrapPtr
dec Bpars
brl parloop
; Create handle to store ruler handles in until we are sure we will succeed.
doneloop lda Rulers
asl a
asl a
ldx #0
call D_NeedHandle,in=(ax:l,#$8000:w),out=(RListHand:l),err=err
jcs killscrap
movelong [RListHand],RLPtr
; Read in all the rulers remembering their handles in the ruler list so we can recover from errors.
stz RHands
ruleinloop jsl D_BeachBall
cmpw RHands,Rulers
jge endrloop
call D_NeedHandle,in=(#X_RulerSize:l,#$8000:w),out=(Ruler:l),err=err
jcs killrulers
movelong [Ruler],RulerPtr
lda RHands
asl a
asl a
tay
movelong Ruler,[RLPtr]:y
inc RHands
call D_Read2,in=(FileRef:w,RulerPtr:l,#X_RulerSize:l),out=(ax:l),err=err
jcs killrulers
tool _HUnlock,in=(Ruler:l)
brl ruleinloop
; If no text blocks exist then branch to handle pictures (ha ha).
endrloop lda Blocks
jeq dopicts
; Create handle to store text block handles in until we are sure we will succeed.
lda Blocks
asl a
asl a
ldx #0
call D_NeedHandle,in=(ax:l,#$8000:w),out=(BListHand:l),err=err
jcs killrulers
movelong [BListHand],BLPtr
; Read in all the text blocks putting their handles in the block list so we can recover from errors.
stz BHands
readbloop jsl D_BeachBall
call D_ReadHandle2,in=(FileRef:w),out=(Block:l),err=err
jcs killblocks
tool _HUnlock,in=(Block:l)
lda BHands
asl a
asl a
tay
movelong Block,[BLPtr]:y
inc BHands
cmpw BHands,Blocks
blt readbloop
; Handle reading picts ( picts not supported at this time ).
dopicts
; Use the reference indexes in the save array to put the text block & ruler handles we have read in
; the scrap paragraphs.
doinsert movelong [SaveArrayHand],SAPtr
movelong [Scrap],ScrapPtr
moveword [ScrapPtr],Bpars
addlong ScrapPtr,#2,ScrapPtr
stz Handles
insertloop moveword [SAPtr],a
asl a
asl a
tay
movelong [BLPtr]:y,[ScrapPtr]
lda Type
bne dorulesub
moveword [SAPtr]:#4,a
bne iloopinc
dorulesub moveword [SAPtr]:#6,a
asl a
asl a
tay
movelong [RLPtr]:y,[ScrapPtr]:#X_scpRulerHand
iloopinc inc Handles
addwl #12,SAptr
addwl PBlocksize,ScrapPtr
cmpw Handles,Bpars
jlt insertloop
; Successfully read in the scrap. Unlock the scrap and dispose of the text block & ruler lists.
; Dispose of the save array and exit with no error.
readdone tool _HUnlock,in=(Scrap:l)
lda Blocks
beq chkrlist
tool _DisposeHandle,in=(BListHand:l)
chkrlist lda Rulers
beq gokillsave
tool _DisposeHandle,in=(RListHand:l)
gokillsave brl killsave
; Error occurred. Dispose of all memory allocated so far.
killblocks lda BHands
beq killblist
dec a
asl a
asl a
tay
tool _DisposeHandle,in=([BLPtr]:y:l)
dec BHands
bra killblocks
killblist tool _DisposeHandle,in=(BListHand:l)
killrulers lda RHands
beq killrlist
dec a
asl a
asl a
tay
tool _DisposeHandle,in=([RLPtr]:y:l)
dec RHands
bra killrulers
killrlist tool _DisposeHandle,in=(RListHand:l)
killscrap tool _DisposeHandle,in=(Scrap:l)
killsave tool _DisposeHandle,in=(SaveArrayHand:l)
exit call D_SetCursor,in=(X_OldCursor:w)
return
ENDP
*****************************************************************************************************
; X_ScWriteWPScrap ( FileRef:word, Type:word )
;
; This routine is called to write both WPScraps and PL text threads from disk. If Type is non-zero
; then write text thread else write WPscrap. FileRef should be the file reference to the already
; opened and correctly positioned file. Memory and disk errors are returned.
;
; It is assumed that the bank has already been set to the Scrap segments bank.
X_ScWriteWPScrap PROC EXPORT
input FileRef:w,Scrap:l,Type:w
local Sptr:l,Pars:w
error err
begin
; Lock down the scrap; point past the paragraph count and call write thread to do the actual work.
tool _HLock,in=(Scrap:l)
movelong [Scrap],Sptr
moveword [Sptr],Pars
addwl #2,Sptr
call X_WriteThread,in=(FileRef:w,Pars:w,Sptr:l,Type:w),err=err
return
ENDP
*****************************************************************************************************
; X_ScWriteThread ( FileRef:word, Pars:word, Scrap:long, Type:word )
;
X_ScWriteThread PROC EXPORT
;Using X_WPScrapData
;Using X_WPFileData
;Using D_IOData
;Using X_ClipData
;Using D_CursorData
input FileRef:w,Pars:w,Scrap:l,Type:w
local Ptr:l,Bpars:w,SaveArraySize:l,SaveArrayHand:l,SAPtr:l
local BListPtr:l,BListhand:l,BLPtr:l,RListHand:l,RLPtr:l
local PicListHand:l,PLPtr:l,Blocks:w,Rulers:w,Picts:w
local BListSize:l,Block:l,Ruler:l,ScrapPtr:l
local PBlockSize:w,Scratch:l,ScratchSize:l
local ScratchPtr:l,Temp2:l,Temp:l
error err
begin
; Save the current cursor and put up the beachball cursor.
moveword >D_CurCursor,X_OldCursor
jsl D_Beachball
stz err
; Set PBlockSize depending on whether we are writing a PL text thread or a WP scrap.
lda Type
bne notwp
moveword #X_ParBlockSize,PBlockSize
bra cont
notwp moveword #(X_ParBlockSize+4),PBlockSize
; Setup local variables. Ptr will point to current location in document scrap and Bpars will contain
; the number of paragraphs in the scrap to go.
cont movelong Scrap,Ptr
moveword Pars,Bpars
; Yuk! We must copy all the paragraph information to a separate array where we will modify things
; like the ruler and text block handles to be indexes instead of handles. ( ie make it a semi-flat
; structure to save to disk. ) If we get a memory error then pass it back to the caller.
tool _Multiply,in=(Bpars:w,#12:w),out=(SaveArraySize:l)
call D_MustHandle,in=(SaveArraySize:l,#0:w),out=(SaveArrayHand:l),err=err
jcs exit
; Yuk! again! We must create lookup array for text block handles.
lda Bpars
asl a
asl a
sta BListSize
ldx #0
call D_MustHandle,in=(ax:l,#0:w),out=(BListHand:l),err=err
jcs killsave
; Yuk! Yuk! We must create lookup array for ruler handles.
call D_MustHandle,in=(#0:w,BListSize:w,#0:w),out=(RListHand:l),err=err
jcs killblist
; Lock down the handle and get their pointers.
rcall D_Deref,in=(SaveArrayHand:ax),out=(SAPtr:ax)
rcall D_Deref,in=(BListHand:ax),out=(BLPtr:ax)
rcall D_Deref,in=(RListHand:ax),out=(RLPtr:ax)
; Clear counts and initialize variables before loop.
stz Blocks
stz Rulers
stz Picts
stzl Block
movelong Scrap,Ptr
; For all paragraphs do:
parloop lda Bpars
jeq endloop
; Check if first time through if so add first text block in scrap to the block lookup array.
lda Block
ora Block+2
bne notfirst
movelong [Ptr],Block
bra addtolist
; Check if the text block currently being pointed to in the scrap is the same as the last text block
; we saw. If not add it to the block lookup array and make it the last block seen. If it is the same
; block then branch to handle the current paragraph ruler.
notfirst cmpl [Ptr],Block
beq dorulers
addtolist lda Blocks
asl a
asl a
tay
movelong [Ptr],[BLPtr]:y
inc Blocks
movelong [Ptr],Block
; Check if ruler exists. If WP scrap and Attr is non-zero then must be a page break paragraph and
; therefore won't have a ruler associated with it. In all other cases ruler should exist.
dorulers lda Type
bne realruler
ldy #X_scpAttr
lda [Ptr],y
jne endruler
; Scan through ruler lookup array trying to find the same ruler handle as the current one {temp}.
realruler ldx #0
movelong [Ptr]:#X_scpRulerHand,Temp
rulerloop txa
cmp Rulers
bge nofindruler
asl a
asl a
tay
cmpl Temp,[RLPtr]:y
beq rulerfound
inx
bra rulerloop
; Ruler found so put its lookup value in the save array.
rulerfound txa
bra putrulenum
; Ruler was not found so we need to add it to the lookup array and bump the ruler count.
nofindruler txa
asl a
asl a
pha
ldy #X_scpRulerHand
lda [Ptr],y
ply
phy
sta [RLPtr],y
ldy #X_scpRulerHand+2
lda [Ptr],y
ply
iny
iny
sta [RLPtr],y
inc Rulers
txa
putrulenum moveword a,[SAPtr]:#6
; Save the lookup value for the current text block, and the remaining paragraph information.
endruler lda Blocks
dec a
sta [SAPtr]
moveword [Ptr]:#X_scpOffset,[SAPtr]:#2
moveword [Ptr]:#X_scpAttr,[SAPtr]:#4
moveword [Ptr]:#X_scpPixels,[SAPtr]:#8
moveword [Ptr]:#X_scpLastLine,[SAPtr]:#10
; Point save array pointer past the paragraph info we just saved. Bump the scrap pointer past the
; paragraph we just processed. Decrement the number of paragraphs left to do and go back for more.
addlong SAPtr,#12,SAPtr
addwl PBlockSize,Ptr
dec Bpars
brl parloop
; Ok we have filled up the save array with all the paragraphs info. Ruler & text block handles have
; been replaced with their lookup values. No save out the paragraph cout and the save array.
endloop moveword Pars,Bpars
call D_Write2,in=(FileRef:w,!Bpars:l,#2:l),out=(ax:l),err=err
jcs killrlist
call D_Write2,in=(FileRef:w,[SaveArrayHand]:l,SaveArraySize:l),out=(ax:l),err=err
jcs killrlist
; Write out rulers
movelong RLPtr,temp
ruleoutloop jsl D_BeachBall
lda Rulers
beq endruleout
movelong [temp],Ruler
tool _HLock,in=(Ruler:l)
call D_Write2,in=(FileRef:w,[Ruler]:l,#X_RulerSize:l),out=(ax:l),err=err
jcs killrlist
tool _HUnlock,in=(Ruler:l)
addwl #4,temp
dec Rulers
bra ruleoutloop
endruleout
; Write out paragraph blocks. Paragraph blocks are written out as a long for the size of the
; paragraph and then the paragraph block is written out. The text block is shrunk by writing
; out the used size for both the block size & used size.
movelong BLPtr,temp
paroutloop jsl D_BeachBall
lda Blocks
jeq dopictout
movelong [temp],Scratch
movelong [Scratch],ScratchPtr
ldy #2
lda [ScratchPtr],y
sta ScratchSize
stz ScratchSize+2
call D_Write2,in=(FileRef:w,!ScratchSize:l,#4:l),out=(ax:l),err=err
jcs killrlist
addwl #2,ScratchPtr
call D_Write2,in=(FileRef:w,ScratchPtr:l,#2:l),out=(ax:l),err=err
jcs killrlist
sublong ScratchSize,#2,ScratchSize
call D_Write2,in=(FileRef:w,ScratchPtr:l,ScratchSize:l),out=(ax:l),err=err
jcs killrlist
addwl #4,temp
dec Blocks
brl paroutloop
; Write out picture blocks ( not implemented in this version ).
dopictout
; Dispose of all the memory that we allocated to save the scrap/thread.
killrlist tool _DisposeHandle,in=(RListHand:l)
killblist tool _DisposeHandle,in=(BListHand:l)
killsave tool _DisposeHandle,in=(SaveArrayHand:l)
exit call D_SetCursor,in=(X_OldCursor:w)
return
ENDP
*****************************************************************************************************
; X_ScImportWP ( FileRef:word )
;
; This routine will read from the given WP document and create a WP scrap from it. If the document
; is blank then warn the user and return an error. Memory & disk errors will be returned.
X_ScImportWP PROC EXPORT
;Using D_IOData
;Using X_WPFileData
input FileRef:w
local Offset:w,TotalOffset:l,Temp:l,Temp2:l,FileRef:w
output Dest:l
error err
begin
; Set the file mark after the file header, and the wp header. This is a hard wired magic number!!
; Yeah!! Isn't programming fun.
call D_SetMark2,in=(FileRef:w,#0:w,#$29C:l),err=err
; Read the WP document as a scrap.
call X_ReadWPScrap,in=(FileRef:w,#0:w),out=(Dest:l),err=err
bcs exit
; Separate the first and last paragraphs into their own text blocks.
call X_MassageWPScrap,in=(Dest:l),err=err
bcc checkblank
call X_DisposeWPScrap,in=(Dest:l)
stzl Dest
bra exit
; If there is one paragraph and its text block is of size 12 then warn user that document is blank.
checkblank movelong [Dest],Temp
Cmpw [Temp],#2
bge exit
movelong [Temp]:#2,Temp2
movelong [Temp2],Temp
Cmpw [Temp]:#2,#13
bge exit
call D_AlertBox,in=(#OKBox:w,#BlankScrap:l),out=(a:w)
call X_DisposeWPScrap,in=(Dest:l)
movelong #-1,err
exit return
BlankScrap STR 'This document is blank.'
ENDP
END