antoine-source/appleworksgs/PL/Src/PFILE.S

1 line
17 KiB
ArmAsm
Executable File

*****************************************************************************************************
; PL I/O Routines
;
; This file contains the routines used by PL to open and save documents.
;
*****************************************************************************************************
load 'macros.dump'
include 'driver.equ'
include 'pl.equ'
IMPORT D_BeachBall
IMPORT D_Deref
IMPORT D_DestroyByRef
IMPORT D_FastMult
IMPORT D_NeedHand
IMPORT D_Read2
IMPORT D_ReadHandle2
IMPORT D_SetCursor
IMPORT D_UnLock
IMPORT D_Write2
IMPORT D_WriteHandle2
IMPORT P_CheckHand
IMPORT P_CurrentWin
IMPORT P_ErrorAlert
IMPORT P_Header
IMPORT P_HeaderSize
IMPORT P_HorizGCount
IMPORT P_HorizGuides
IMPORT P_InitDoc
IMPORT P_KillPage
IMPORT P_LastObj
IMPORT P_LoadPage
IMPORT P_LoadWindowStuff
IMPORT P_MergeGuides
IMPORT P_NotActive
IMPORT P_OBJSIZES
IMPORT P_ObjList
IMPORT P_PInfoSize
IMPORT P_Page
IMPORT P_PageArray
IMPORT P_PageCount
IMPORT P_SavePage
IMPORT P_SaveWindowStuff
IMPORT P_ShowDoc
IMPORT P_UseTemplate
IMPORT P_Version
IMPORT P_VertGCount
IMPORT P_VertGuides
IMPORT T_ReThread
IMPORT X_ReadWPScrap
IMPORT X_WriteWPScrap
IMPORT X_DisposeThread
*****************************************************************************************************
; P_Thread2Pair ( ThreadHdl:long ): PageNo:word, ObjNo:word
;
; This routine is called to determine the page and object number for a given text thread. The page
; and object numbers will be used when saving to disk to replace the handles. These values can be
; used on an Open to correctly relink the new handles in the same way.
P_Thread2Pair PROC EXPORT
;Using P_Data
;Using P_ObjData
input ThreadHdl:l
output PageNo:w,ObjNo:w
local Hdl:l,Ptr:l,ThreadPtr:l,ObjHdl:l,ObjPtr:l,Offset:l
begin
; If thread handle is NIL then blow it off.
cpzl ThreadHdl
beq NoThread
; Get page number from the thread.
movelong [ThreadHdl],ThreadPtr
moveword [ThreadPtr]:#P_PageNo,PageNo
; Get pointer to page entry in the page array.
tool _Multiply,in=(PageNo:w,#P_PInfoSize:w),out=(Offset:l)
movelong P_PageArray,Hdl
movelong [Hdl],Ptr
addlong Ptr,Offset,Ptr
; Scan page object list to see if we can find the thread we are looking for. Get its object number.
movelong [Ptr],ObjHdl
stz ObjNo
loop cmpl ObjHdl,ThreadHdl
beq exit
movelong [ObjHdl],ObjPtr
movelong [ObjPtr],ObjHdl
inc ObjNo
bra loop
; The thread was NIL so return page number and object number of -1.
NoThread moveword #-1,PageNo
sta ObjNo
exit return
ENDP
*****************************************************************************************************
; P_Pair2Thread ( PageNo:word, ObjNo:word ): ThreadHdl:long
;
; This routine is called to determine the text thread corresponding to the given text object for
; the given page.
P_Pair2Thread PROC EXPORT
;Using P_Data
;Using P_ObjData
input PageNo:w,ObjNo:w
output ObjHdl:l
local Hdl:l,Ptr:l,ObjPtr:l,Offset:l
begin
; If page number is -1 then no thread exists for this page object; return NIL.
cmpw PageNo,#-1
beq NoThread
; Get pointer to page entry in the page array.
tool _Multiply,in=(PageNo:w,#P_PInfoSize:w),out=(Offset:l)
movelong P_PageArray,Hdl
movelong [Hdl],Ptr
addlong Ptr,Offset,Ptr
; Scan object array for the given page to find the object handle for the given object number.
movelong [Ptr],ObjHdl
ldx #0
loop cpx ObjNo
beq exit
movelong [ObjHdl],ObjPtr
movelong [ObjPtr],ObjHdl
inx
bra loop
; No thread exists for this page/object return NIL.
NoThread stzl ObjHdl
exit return
ENDP
*****************************************************************************************************
; P_SetParag ( ObjectPtr:long )
;
; This routine is called to put the given objects paragraph handle into all the text threads in
; its linked list.
P_SetParag PROC EXPORT
;Using P_ObjData
input objptr:l
local objhdl:l,paraghdl:l
begin
movelong [objptr]:#P_ParagHdl,paraghdl
objloop cpzl [objptr]:#P_NThread
beq exit
movelong [objptr]:#P_NThread,objhdl
movelong [objhdl],objptr
movelong paraghdl,[objptr]:#P_ParagHdl
bra objloop
exit return
ENDP
*****************************************************************************************************
; P_OpenDoc ( FileId:word, WindowPtr:long )
;
; This routine will handle reading in a page layout document with the given file reference. The
; file has already been opened by the driver and the file mark moved to the start of the document
; data. Memory or file I/O errors are returned to the driver which will handle closing the file and
; alerting the user.
P_OpenDoc PROC EXPORT
;Using P_Data
;Using P_ObjData
;Using D_IOData
;Using P_RulerData
input fileid:w,window:l
local page:w,pagecount:w,oldpage:w,tmp:l,tmphdl:l
local oldwin:l,tmpobj:l,objptr:l,xhdl:l,xtype:w
local xobj:l,xobjhdl:l,table:l,refcon:l,lastpage:w
; these 4 variables are clustered. Do not rearrange or seperate.
local templ:w,hguide:w,vguide:w,count:w
error err
begin +b
; Clear local variables and put up the watch cursor.
stzl tmp
stzl tmphdl
stzl xobj
stzl xobjhdl
stzl table
stzl refcon
stzl oldwin
stzl tmpobj
stzl objptr
stz pagecount
call D_SetCursor,in=(#WatchCursor:w)
; Page out current window information. Set table to point to table of object sizes.
movelong P_CurrentWin,oldwin
call P_SaveWindowStuff,in=(oldwin:l)
movelong #P_OBJSIZES,table
; If we can't get 32k then probably shouldn't be trying to open a document. Return driver a memory
; error.
call P_CheckHand,in=(#$8000:l),err=(err)
jcs exit
; Read header information for the file. If read error then return with error to driver.
call D_Read2,in=(fileid:w,#P_Header:l,#P_HeaderSize:l),out=(ax:l),err=(err)
jcs exit
; Check if PL id present in file if not then this file must be damaged or not a real PL file. Since
; we are handling the error return -1 to the driver.
jsr chkversion
jcs exit
; Traverse the document page by page, object by object...
; File looks OK so far; clear error status and get temp object for use in loading file. If we can't
; get it return to the driver with a mem error, else lock down the temp object and clear the temp
; object handle variable.
stz err
call D_NeedHand,in=(#P_TextObjSize:l),out=(xobjhdl:l),err=(err)
jcs exit
rcall D_Deref,in=(xobjhdl:ax),out=(xobj:ax)
movelong #0,xhdl
; Initialize the document structure. Get refcon in case we need to dispose it on error.
call P_InitDoc,in=(window:l),out=(refcon:l),err=err
jcs killxobj
; Initialize pagecount (including master pages) and current/last page.
addword P_PageCount,#2,pagecount
moveword #-1,page
sta lastpage
; Try to allocate a page array large enough to hold all the pages in the document. If we can't then
; dispose of the temp object and the refcon we allocated.
spacelong
tool _Multiply,in=(#P_PInfoSize:w,pagecount:w),out=(:l)
call D_NeedHand,err=(err)
pulllong P_PageArray
jcs killrefcon
; Remember what the old page used to be. Clear loop variables and bump to next page and last page.
moveword P_Page,oldpage
pageloop stzl P_HorizGuides
stzl P_VertGuides
stzl P_ObjList
stzl P_LastObj
inc page
inc lastpage
; Read count, vguide, hguide and templ in one call. If error reading then dispose of all pages read
; so far, refcon, and xobj before returning mem error to the driver. Set global based on values read.
call D_Read2,in=(fileid:w,!count:l,#8:l),out=(ax:l),err=(err)
jcs killpages
moveword vguide,P_VertGCount
moveword hguide,P_HorizGCount
moveword templ,P_UseTemplate
; Read in objects from file.
objloop jsl D_BeachBall
dec count
jmi doneobj
; Get object information. If error then dispose of all memory allocated so far.
stzl xhdl
call D_Read2,in=(fileid:w,xobj:l,#P_TextObjSize:l),out=(ax:l),err=(err)
jcs killpages
; Check if object type is text object. If so check if text object has a thread associated with it.
; If not then ready to add object to page layout, else read in text thread for the object.
cmpw [xobj]:#P_Type,#P_ALPHA
bne CkPict
cmpw [xobj]:#P_PThread,#-1
jne DidObj
call X_ReadWPScrap,in=(FileId:w,#1:w),out=(tmp:l),err=err
jcs killpages
; Put text thread into the temp object. Unlock the text thread since read WP returns it locked.
movelong tmp,xhdl
moveword #P_Alpha,xtype
movelong xhdl,[xobj]:#P_ParagHdl
rcall D_UnLock,in=(xhdl:ax)
bra DidObj
; Check if object type is PICT. If so read in PICT handle.
CkPict cmp #P_PICTURE
bne DidObj
call D_ReadHandle2,in=(fileid:w),out=(tmp:l),err=(err)
jcs killpages
; Put picture handle in temp object. Unlock the pict handle since read handle returns it locked.
movelong tmp,xhdl
moveword #P_Picture,xtype
movelong xhdl,[xobj]:#P_PictHandle
rcall D_UnLock,in=(xhdl:ax)
; Xobj now has entire object including picture or text thread handles. Check if valid object type
; if not the file must be corrupt; warn user and dispose of all memory so far allocated.
DidObj cmpw [xobj]:#P_Type,#P_Picture+1
blt oktype
moveword #-1,err
call P_ErrorAlert,in=(#2:w)
brl killpages
; Make copy of temp object to put in the data structure. If memory error then dispose of all memory
; so far allocated and return with mem error. { use table to determine true size needed for object }
oktype dec a
asl a
asl a
tay
movelong [table]:y,tmp
call D_NeedHand,in=(tmp:l),out=(tmphdl:l),err=(err)
jcs killpages
tool _BlockMove,in=(xobj:l,[tmphdl]:l,tmp:l)
stzl xhdl
; Get pointer to new object. Add object to linked list.
movelong [tmphdl],tmp
IsNil P_ObjList
bne NotFirst
movelong tmphdl,P_ObjList
movelong tmphdl,P_LastObj
movelong #0,[tmp]
movelong #0,[tmp]:#P_Prev
bra DidInsert
NotFirst movelong P_LastObj,[tmp]:#P_Prev
movelong #0,[tmp]
movelong tmphdl,P_LastObj
movelong [tmp]:#P_Prev,tmphdl
movelong [tmphdl],tmp
movelong P_LastObj,[tmp]
DidInsert brl objloop
; Object successfully added to page data structure. If horz. guides exists then read its handle.
doneobj lda hguide
beq CkVguide
call D_ReadHandle2,in=(fileid:w),out=(P_HorizGuides:l),err=(err)
bcc GotH
stzl P_HorizGuides
brl killpages
GotH rcall D_UnLock,in=(P_HorizGuides:ax)
; If vert. guides exist then read its handle.
CkVguide lda vguide
beq DidGuides
call D_ReadHandle2,in=(fileid:w),out=(P_VertGuides:l),err=(err)
bcc GotV
stzl P_VertGuides
brl killguides
GotV rcall D_UnLock,in=(P_VertGuides:ax)
; Save page information. And go back for any remaining pages to be loaded.
DidGuides call P_SavePage,in=(page:w)
dec pagecount
jne pageloop
; Verify that file is still valid by checking version numbers.
call D_Read2,in=(fileid:w,#P_Header:l,#2:l),out=(ax:l),err=(err)
jcs gokillgs
jsr chkversion
gokillgs jcs killguides
stz err
; File completely read in. Now repair threads so they use real handles instead of page number and
; object number offsets.
; Repair threads, part I. Loop through all objects on all pages updating their next & previous thread
; handles if they are text objects.
addword P_PageCount,#2,pagecount
moveword #-1,page
pageloop2 inc page
call P_LoadPage,in=(page:w)
stz count
movelong P_ObjList,tmpobj
objloop2 jsl D_BeachBall
IsNil tmpobj
jeq doneobj2
rcall D_Deref,in=(tmpobj:ax),out=(objptr:ax)
cmpw [objptr]:#P_Type,#P_ALPHA
bne DidText
call P_Pair2Thread,in=([objptr]:#P_PThread:l),out=([objptr]:#P_PThread:l)
call P_Pair2Thread,in=([objptr]:#P_NThread:l),out=([objptr]:#P_NThread:l)
DidText rcall D_UnLock,in=(tmpobj:ax)
movelong [objptr],tmpobj
brl objloop2
doneobj2 call P_SavePage,in=(page:w)
dec pagecount
jne pageloop2
; Repair threads, part II. Loop through all objects on all pages and if object is a text object then
; set the paragraph blocks for all objects in the list then rethread the object.
addword P_PageCount,#2,pagecount
moveword #-1,page
pageloop3 inc page
call P_LoadPage,in=(page:w)
stz count
movelong P_ObjList,tmpobj
objloop3 jsl D_BeachBall
IsNil tmpobj
jeq doneobj3
rcall D_Deref,in=(tmpobj:ax),out=(objptr:ax)
cmpw [objptr]:#P_Type,#P_ALPHA
jne DidText3
cpzl [objptr]:#P_PThread
bne DidText3
call P_SetParag,in=(objptr:l)
call T_ReThread,in=(tmpobj:l)
DidText3 rcall D_UnLock,in=(tmpobj:ax)
movelong [objptr],tmpobj
brl objloop3
doneobj3 call P_SavePage,in=(page:w)
dec pagecount
jne pageloop3
; Successfully loaded file get ready to show document. Load the original page that document was saved
; on and merge guides. Then dispose of xobj.
call P_ShowDoc,in=(window:l),err=(err)
bcs killpages
call P_LoadPage,in=(oldpage:w)
call P_MergeGuides
brl killxobj
; Error loading file so dispose of memory we have allocated.
killguides lda hguide
beq killvguide
cpzl P_HorizGuides
beq killvguide
tool _DisposeHandle,in=(P_HorizGuides:l)
killvguide lda vguide
beq killpages
cpzl P_VertGuides
beq killpages
tool _DisposeHandle,in=(P_VertGuides:l)
killpages call P_SavePage,in=(page:w)
riploop jsl D_BeachBall
call P_KillPage,in=(lastpage:w,#1:w)
dec lastpage
bpl riploop
killparray tool _DisposeHandle,in=(P_PageArray:l)
; Error loading file so dispose of memory we have allocated.
killrefcon tool _DisposeHandle,in=(RefCon:l)
killxobj tool _DisposeHandle,in=(xobjhdl:l)
; If paragraph handle exists in the temp object make sure to dispose of it too.
cpzl xhdl
beq exit
cmpw xtype,#P_Picture
beq killpict
call X_DisposeThread,in=(xhdl:l,#1:w)
bra exit
killpict tool _KillPicture,in=(xhdl:l)
; Restore old window before returning.
exit call P_LoadWindowStuff,in=(oldwin:l)
return
;...................................................................................................;
; Check if PL id present in file if not then this file must be damaged or not a real PL file. Since
; we are handling the error return -1 to the driver.
chkversion moveword #-1,err
lda P_Version
xba
and #$FF
cmp #P_ID
beq CkVers1
ldx #2
bra doalert
; Warn user that this version of file cannot be loaded.
CkVers1 lda P_Version
and #$FF
cmp #P_VNum
beq chkvok
ldx #3
doalert call P_ErrorAlert,in=(x:w)
sec
rts
chkvok clc
rts
;...................................................................................................;
ENDP
;---------------------------------------------------------------------------
;
; P_SaveDoc (Fileid:w,Winptr:l,BogusType:w)
;
P_SaveDoc PROC EXPORT
;Using P_Data
;Using P_ObjData
;Using D_IOData
;Using D_GlobalData
input fileid:w,winptr:l,bogusType:w
local oldwin:l,oldpage:w
local xobjhdl:l,xobj:l,pagecount:w,page:w
local tmpobj:l,objptr:l
; these 4 variables are clustered. Do not rearrange or seperate.
local templ:w,hguide:w,vguide:w,count:w
;
error err
begin +b
call D_SetCursor,in=(#WatchCursor:w)
cmpl WinPtr,P_CurrentWin
beq Active
inc P_NotActive
Active
movelong P_CurrentWin,oldwin
call P_LoadWindowStuff,in=(winptr:l)
moveword P_Page,oldpage
call P_SavePage,in=(P_Page:w)
moveword #P_VersNum,P_Version
call D_Write2,in=(fileid:w,#P_Header:l,#P_HeaderSize:l),out=(ax:l),err=(err)
jcs Whoops ;**
; ;************************************
; Traverse the document, page by page
; object by object
call D_NeedHand,in=(#P_TextObjSize:l),out=(xobjhdl:l),err=(err)
jcs Whoops ;**
rcall D_Deref,in=(xobjhdl:ax),out=(xobj:ax)
addword P_PageCount,#2,pagecount
moveword #-1,page
pageloop inc page
call P_LoadPage,in=(page:w)
stz count
movelong P_ObjList,tmpobj
countloop IsNil tmpobj
beq gotcount
inc count
movelong [tmpobj],objptr
movelong [objptr],tmpobj
bra countloop
gotcount moveword P_VertGCount,vguide
moveword P_HorizGCount,hguide
moveword P_UseTemplate,templ
call D_Write2,in=(fileid:w,!count:l,#8:l),out=(ax:l),err=(err)
jcs Whoops ;**
movelong P_ObjList,tmpobj
objloop IsNil tmpobj
jeq doneobj
rcall D_Deref,in=(tmpobj:ax),out=(objptr:ax)
cmpw [objptr]:#P_Type,#P_ALPHA
jne CkPict
tool _BlockMove,in=(objptr:l,xobj:l,#P_TextObjSize:l)
in [xobj]:#P_PThread:l
out [xobj]:#P_PThread:l
xcall P_Thread2Pair
in [xobj]:#P_NThread:l
out [xobj]:#P_NThread:l
xcall P_Thread2Pair
call D_Write2,in=(fileid:w,xobj:l,#P_TextObjSize:l),out=(ax:l),err=(err)
jcs Whoops ;**
moveword [objptr]:#P_PThread,a
iny
iny
ora [objptr],y
jne DidObj
call X_WriteWPScrap,in=(fileid:w,[xobj]:#P_ParagHdl:l,#1:w),err=(err)
jcs whoops ;**
brl DidObj
CkPict cmp #P_PICTURE
bne NormObj
call D_Write2,in=(fileid:w,objptr:l,#P_TextObjSize:l),out=(ax:l),err=(err)
jcs Whoops ;**
call D_WriteHandle2,in=(fileid:w,[objptr]:#P_PictHandle:l),err=(err)
jcs Whoops ;**
pushlong [objptr]:#P_PictHandle
_HUnlock
bra DidObj
NormObj
call D_Write2,in=(fileid:w,objptr:l,#P_TextObjSize:l),out=(ax:l),err=(err)
jcs Whoops ;**
DidObj rcall D_UnLock,in=(tmpobj:ax)
movelong [objptr],tmpobj
brl objloop
doneobj
lda hguide
beq CkVguide
call D_WriteHandle2,in=(fileid:w,P_HorizGuides:l),err=(err)
jcs Whoops ;**
rcall D_UnLock,in=(P_HorizGuides:ax)
CkVguide
lda vguide
beq DidGuides
call D_WriteHandle2,in=(fileid:w,P_VertGuides:l),err=(err)
jcs Whoops ;**
rcall D_UnLock,in=(P_VertGuides:ax)
DidGuides dec pagecount
jne pageloop
call D_Write2,in=(fileid:w,#P_Header:l,#2:l),out=(ax:l),err=(err)
; bcs Whoops ;**
;
; bra exit
whoops
; The driver now does all file cleanup!
exit
tool _DisposeHandle,in=(xobjhdl:l)
call P_LoadPage,in=(oldpage:w)
call P_LoadWindowStuff,in=(oldwin:l)
stz P_NotActive
return
ENDP
END