***************************************************************************************************** * 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