***************************************************************************************************** * WP Copy/Paste Routines * * This file contains the routines used by WP to handle cutting and pasting. * ***************************************************************************************************** load 'macros.dump' include 'driver.equ' include 'wp.equ' include 'scrap.equ' IMPORT D_BeachBall IMPORT D_Deref IMPORT D_GrowLHandle IMPORT D_KillFont IMPORT D_MemoryError IMPORT D_UndoMemError IMPORT D_Unlock IMPORT W_CalcDocRect IMPORT W_CalcFBytes IMPORT W_CalcPages IMPORT W_CollapseRulers IMPORT W_CurDoc IMPORT W_DelSelect IMPORT W_EndLine IMPORT W_EndOffset IMPORT W_EndPar IMPORT W_FindFont IMPORT W_FindLine IMPORT W_GetAddr IMPORT W_GetDoc IMPORT W_GetParRec IMPORT W_JunkLeft IMPORT W_JunkRight IMPORT W_LastP IMPORT W_LessRoom IMPORT W_LineToTopPixel IMPORT W_MakeCaret IMPORT W_MakeCr IMPORT W_MakeEmptyBlock IMPORT W_MakeRoom IMPORT W_MakeLines IMPORT W_MaxP IMPORT W_PHandle IMPORT W_PPtr IMPORT W_PasteLine IMPORT W_PasteOffset IMPORT W_PastePar IMPORT W_PtToText IMPORT W_PutOnScreen IMPORT W_ReadFont IMPORT W_Selected IMPORT W_SelectOff IMPORT W_SetFullREct IMPORT W_StartLine IMPORT W_StartOffset IMPORT W_StartPar IMPORT W_UnUseRuler IMPORT W_UndoEndLine IMPORT W_UndoEndOffset IMPORT W_UndoEndPar IMPORT W_UndoOff IMPORT W_UndoOn IMPORT W_UndoStartLine IMPORT W_UndoStartOffset IMPORT W_UndoStartPar IMPORT W_UndoHandle IMPORT W_UpdateText IMPORT W_UseRuler IMPORT W_View IMPORT W_WpCopy IMPORT W_WriteFBytes2 IMPORT X_DisposeScrap IMPORT X_PostScrap IMPORT X_SwitchFont IMPORT caretOff ENTRY W_PasteText ENTRY W_SplitBlock ***************************************************************************************************** ; W_MyPaste ( WindowPtr:long, Scrap:long, Type:word, Paste:word, Where:long ) ; ; This is the main paste vector for WP. If the given scrap is of the correct type it will be ; pasted into the document for the given window. If Paste is 1 then use the Where field to ; determine where in the window the paste should take place. If Paste is 2 then paste is coming ; from an import. Memory errors are returned. Where is in window local coordinates. W_MyPaste PROC EXPORT ;Using wpglobals input window:l,Scrap:l,type:w,Paste:w,where:l local rect:r,ParCnt:w,WPtr:l,par:w,OldDoc:l error err begin +b ; Make sure that the scrap is a WP scrap if not dispose of it and exit with error #1. stz err cmpw type,#WPText beq savedoc inc err call X_DisposeScrap,in=(Type:w,Scrap:l) brl _exit ; Save current document so it can be restored before exiting. Turn carret off and clear the undo. savedoc movelong W_CurDoc,OldDoc tool _SetPort,in=(W_CurDoc:l) jsl caretOff jsl W_UndoOff ; Set port to given window and kill current font. Bring in document information. tool _SetPort,in=(window:l) jsl D_KillFont call W_GetDoc,in=(window:l) ; Strip page breaks if we are pasting into the header or footer of the document. Note: PageBreaks ; are guaranteed to always have a carriage return after them. ( ie next paragraph is guaranteed to be ; a real paragraph - no consecutive page breaks paragraph blocks ). Also Page break paragraphs will ; have for their text blocks the same text block used for the text before the page break. lda W_View jeq NoKillPB movelong [scrap],WPtr moveword [WPtr],ParCnt addwl #2,WPtr parloop cmpw [WPtr]:#W_pAttr,#W_PgBrk bne nextpar movelong #0,[WPtr]:#W_pLineHand moveword #0,[WPtr]:#W_pAttr moveword #1,[WPtr]:#W_pLastLine movelong [WPtr]:#W_pBytes+W_pRulerHand,[WPtr]:#W_pRulerHand call W_UseRuler,in=(#1:w,[WPtr]:#W_pBytes+W_pRulerHand:l) nextpar addwl #W_pBytes,WPtr dec ParCnt bne parloop ; If placement type paste then deselect current text and move insertion point to new place in text ; before doing the paste. NoKillPB cmpw paste,#1 bne noplace jsl W_SelectOff call W_PtToText,in=(Where:l),out=(W_StartPar:w,W_StartLine:w,W_StartOffset:w) jsl W_MakeCaret ; Make sure the given paragraph line is on the screen. Get current document rect and adjust top of ; rect based to top pixel of start line. noplace call W_PutOnScreen,in=(W_StartPar:w,W_StartLine:w,#0:l) call W_CalcDocRect,in=(!rect:l) call W_LineToTopPixel,in=(W_StartPar:w,W_StartLine:w),out=(rect:w,a:w) ; If directional paste or import then deselect and don't allow undo. lda paste beq RegUndo jsl W_DelSelect brl NoUndo ; Clear undo handle. If something is selected then save copy of it in undo handle. If we can't get ; enough memory for undo copy then ask if should continue anyway. RegUndo stzl W_UndoHandle lda W_Selected beq NoSelD spacelong pushword W_StartPar pushword W_StartLine pushword W_StartOffset pushword W_EndPar pushword W_EndLine pushword W_EndOffset jsl W_WpCopy sta err pla plx bcc putcopy call D_UndoMemError,out=(a:w) cmp #OK beq noundo brl exit ; Save copy of selected text in undo handle then delete selected text from document. putcopy movelong ax,W_UndoHandle jsl W_DelSelect ; Enable undo menu item and place undo text. Remember undo information to restore selection. NoSelD call W_UndoOn,in=(#W_PasteUndo:w) moveword W_StartPar,W_UndoStartPar moveword W_StartLine,W_UndoStartLine moveword W_StartOffset,W_UndoStartOffset ; Paste the scrap into the document. If memory error then return error to driver. NoUndo pha pha pha pushlong Scrap pushword W_StartPar pushword W_StartLine pushword W_StartOffset jsl W_PasteText sta err bcc NoErr pla pla pla bra exit ; Successfully pasted text into document. Set new values for start offset, line, and paragraph. NoErr pullword W_StartOffset pullword W_StartLine pullword W_StartPar ; Save end position after paste into the undo information. moveword W_StartPar,W_UndoEndPar moveword W_StartLine,W_UndoEndLine moveword W_StartOffset,W_UndoEndOffset ; Erase the clip and erase the document rect; then update its contents. tool _ClipRect,in=(!rect:l) tool _EraseRect,in=(!rect:l) jsl W_UpdateText ; Set clip rect to port rect; put up caret; and collapse rulers. exit jsl W_SetFullRect jsl W_MakeCaret jsl W_CollapseRulers ; Restore old document. call W_GetDoc,in=(OldDoc:l) _exit return ENDP ***************************************************************************************************** ; W_GetCopy ( ): CopyHandle:xy ; ; This routine will return a wpscrap for the current selection. A-reg will contain any errors and ; carry flag is set accordingly. W_GetCopy PROC EXPORT spacelong pushword W_StartPar pushword W_StartLine pushword W_StartOffset pushword W_EndPar pushword W_EndLine pushword W_EndOffset jsl W_WpCopy plx ply rts ENDP ***************************************************************************************************** ; W_MyCut ( WindowPtr:long ):ImageRoutine:long ; ; This routine is the cut vector entry point. It will copy the current selection and then delete ; it from the document. If not enough memory exists to copy then user will be asked told not enough ; memory to undo and be asked to continue or not. ImageRoutine is the routine to be called to draw ; the outline of what is being copied. W_MyCut PROC EXPORT ;Using wpglobals input window:l local Handle:l,OldDoc:l output ImageRoutine:l error err begin +b ; Remember old active document and set document and port for given window. stzl ImageRoutine movelong W_CurDoc,OldDoc call W_GetDoc,in=(Window:l) tool _SetPort,in=(Window:l) ; If nothing is current selected then simply exit. lda W_Selected jeq exit ; Attempt to copy the current selection. If we can't get copy then return memory error to the driver. jsr W_GetCopy sta err jcs exit movelong xy,handle ; Can perform the copy so now clear caret and undo. jsl CaretOff jsl W_UndoOff ; Try and get copy for undo. If we can't then ask user whether we should continue or not. jsr W_GetCopy sta err bcc putundo call D_UndoMemError,out=(a:w) cmp #OK beq noundo stz err tool _DisposeHandle,in=(handle:l) bra exit ; Have enough memory for undo copy. Save it in undo handle and setup undo menu item. putundo movelong xy,W_UndoHandle call W_UndoOn,in=(#W_CutUndo:w) ; Post the scrap, point to our image routine, set clip rect to the entire port, and delete the ; current selection. noundo call X_PostScrap,in=(#WPText:w,Handle:l) ; movelong #W_MyImage,ImageRoutine jsl W_SetFullREct jsl W_DelSelect ; Restore old document. exit call W_GetDoc,in=(OldDoc:l) return ENDP ***************************************************************************************************** ; W_MyCopy ( WindowPtr:long ):ImageRoutine:long, Type:word, Scrap:long ; ; This routine is the copy vector entry point. It will copy the current selection. Memory errors ; are returned. ImageRoutine is the routine to draw an image of the scrap for dragging. Passes back ; zero for no scrap. W_MyCopy PROC EXPORT ;Using WPGlobals input window:l output ImageRoutine:l,stype:w,OutHandle:l error err begin +b ; Clear error status and return scrap type. Save current document on stack and set current document ; to the given window's document. (and port) stz err stz stype stzl ImageRoutine pushlong W_CurDoc call W_GetDoc,in=(window:l) tool _SetPort,in=(window:l) ; If nothing is selected then ignore call. lda W_Selected jeq exit ; Turn off caret and clear undo buffer. jsl CaretOff jsl W_UndoOff ; Get copy of current selection. If error then exit returning error to driver, else return wpscrap ; and type. Set Imageroutine. jsr W_GetCopy sta err bcs exit movelong xy,outhandle moveword #WPText,stype ; movelong #W_MyImage,ImageRoutine ; Restore old document. exit jsl W_GetDoc return ENDP ***************************************************************************************************** ; W_MyImage ( Where:long ) ; ; This routine draw a rect 0,0,50,120 at where. ; Note: No longer used. ; ;W_MyImage PROC EXPORT ; input where:l ; local rect:r ; begin +b ; ; movelong where,rect ; addword where,#50,rect+4 ; addword where+2,#120,rect+4+2 ; tool _FrameRect,in=(!Rect:l) ; ; return ; ; ENDP ***************************************************************************************************** ; W_PasteText ( Handle:l, Par:w, Line:w, Offset:w ): EndPar:w, EndLine:w, EndOffset:w ; ; This routine does the actually work of pasting a scrap handle @ the given paragraph, line, and ; offset. The ending paragraph, line, and offset are returned. Memory errors are returned as well. W_PasteText PROC EXPORT ;Using wpglobals input handle:l,par:w,line:w,offset:w output Outpar:w,Outline:w,Outoffset:w local ptr:l,ParRec1:l,ParRec2:l,Block1:l,Block2:l local col1:w,font1:l,col2:w,font2:l,FBytes:l,TPtr:l local bytes:l,NewLastP:w,NewMaxP:w,NewPars:w,temp:w local BegRul:w,EndRul:w,RulRec:l,Offset1:w,Offset2:w,Ptr2:l local TextPtr:l,NewSize:l error err begin ; Save paragraph, line, and offset in global variables. Spin the beach ball. moveword par,W_PastePar moveword line,W_PasteLine moveword offset,W_PasteOffset jsl D_BeachBall ; Clear error status, flags, and high word of byte counters. stz err stz bytes+2 stz FBytes+2 stz BegRul stz EndRul ; Lock down the scrap handle. Point ParRec1 to first paragraph entry in scrap. rcall D_Deref,in=(handle:ax),out=(ptr:ax) addlong #2,ptr,ParRec1 ; Point ParRec2 to last paragraph entry in scrap. spacelong lda [ptr] dec a pha pushword #W_pBytes _Multiply addlong s,ParRec1,ParRec2 ; Check if first paragraph entry is a page break. If it is we will need to add a carriage return ; paragraph to the scrap before we can process it. cmpw [ParRec1]:#W_pAttr,#W_PgBrk bne NoTopPB jsr addcrtop jcs killscrap NoTopPB call W_JunkLeft,in=(par:w,line:w,offset:w),out=(a:w) sta Offset1 sta W_PasteOffset cmp #W_TextHeader bne NoBR inc BegRul NoBr call W_JunkRight,in=(par:w,line:w,offset:w),out=(x:w) stx Offset2 lda par jsl W_GetAddr movelong ax,Ptr2 cmpb [Ptr2],#cr bne NoEr inc EndRul NoEr rcall D_Deref,in=([ParRec1]:ax),out=(Block1:ax) rcall D_Deref,in=([ParRec2]:ax),out=(Block2:ax) ;get font stuff pha pha pha pha pha pha pushword par pushword line pushword Offset1 jsl W_FindFont lda par ldx Offset1 jsl W_GetAddr phx pha lda par ldx Offset2 jsl W_GetAddr phx pha jsl W_ReadFont moveword 1:s,col1 moveLong 3:s,font1 pushlong handle jsl X_SwitchFont ; done font stuff moveword W_LastP,NewLastP moveword W_MaxP,NewMaxP lda [ptr] cmp #2 bcc NoCheck sec sbc #2 ;check for a possible future mem error sta NewPars clc adc W_LastP sta NewLastP inc a inc a cmp W_MaxP bcc NoCheck clc adc #5 sta NewMaxP tool _Multiply,in=(NewMaxP:w,#W_pBytes:w),out=(NewSize:l) call D_GrowLHandle,in=(NewSize:l,W_PHandle:l),out=(W_PPtr:l),err=err bcc NoCheck brl killscrap NoCheck moveword NewMaxP,W_MaxP subword Offset2,Offset1,x beq NoKillF moveword Offset1,offset pushword par pushword offset phx jsl W_LessRoom NoKillF movelong [Block1]:#W_BHeader,Font2 moveword [Block1]:#W_BHeader+4,a and #$ff sta col2 call W_CalcFBytes,in=(font1:l,col1:w,font2:l,col2:w),out=(Fbytes:w) jsl D_BeachBall lda [ptr] cmp #1 jeq JustOne ; this is for the case that there is a cr pushword Par pushword line pushword offset jsl W_MakeCr pushword par jsl W_SplitBlock jsl D_BeachBall subword [Block1]:#W_BUsed,#W_BHeader+W_TextHeader+1,bytes pushword par pushword offset addword bytes,FBytes,s jsl W_MakeRoom movelong [Block1]:#W_BHeader,font2 moveword [Block1]:#W_BHeader+4,a and #$ff sta col2 lda par ldx offset jsl W_GetAddr movelong ax,TPtr pha pushword par pushword offset pushlong Font1 pushword col1 pushlong Font2 pushword col2 jsl W_WriteFBytes2 subword fbytes,s,fbytes addlong Block1,#W_BHeader+W_TextHeader,s addlong TPtr,FBytes,s pushword #0 pushword bytes _BlockMove jsl D_BeachBall lda par inc a ldx #0 jsl W_GetAddr movelong ax,TPtr movelong [Block2]:#W_BHeader,[TPtr] moveword [Block2]:#W_BHeader+3,[TPtr]:#3 subword [Block2]:#W_BUsed,#W_BHeader+W_TextHeader+1,bytes spacelong spaceword pushlong font2 pushword col2 addlong Block2,#W_BHeader+W_TextHeader,TPtr pushlong TPtr addlong TPtr,bytes,s jsl W_ReadFont pullword col2 pullLong font2 pha pushlong font2 pushword col2 pushlong font1 pushword col1 jsl W_CalcFBytes pullword FBytes lda par inc a pha pushword #W_TextHeader addword bytes,FBytes,s jsl W_MakeRoom jsl D_BeachBall pushlong TPtr lda par inc a ldx #W_TextHeader jsl W_GetAddr movelong ax,TPtr phx pha pushword #0 pushword bytes _BlockMove jsl D_BeachBall pha lda par inc a pha addword #W_TextHeader,bytes,s pushlong font2 pushword col2 pushlong font1 pushword col1 jsl W_WriteFBytes2 subword fbytes,s,fbytes addword TPtr,bytes,a addword a,FBytes,TPtr lda par inc a ldx #0 jsl W_GetAddr sta temp subword TPtr,temp,OutOffset pushlong [ParRec1] _DisposeHandle pushlong [ParRec2] _DisposeHandle jsl D_BeachBall lda BegRul beq NotInCr rcall W_GetParRec,in=(par:a),out=(RulRec:ax) call W_UnUseRuler,in=(#1:w,[RulRec]:#W_pRulerHand:l) movelong [ParRec1]:#W_pRulerHand,[RulRec]:#W_pRulerHand bra DoneRul NotInCr call W_UnUseRuler,in=(#1:w,[ParRec1]:#W_pRulerHand:l) DoneRul lda EndRul beq NotInCr2 lda par inc a jsl W_GetParRec movelong ax,RulRec call W_UnUseRuler,in=(#1:w,[RulRec]:#W_pRulerHand:l) movelong [ParRec2]:#W_pRulerHand,[RulRec]:#W_pRulerHand bra DoneRul2 NotInCr2 call W_UnUseRuler,in=(#1:w,[ParRec2]:#W_pRulerHand:l) DoneRul2 jsl D_BeachBall lda [ptr] cmp #2 jeq W_AllSet lda par inc a jsl W_GetParRec movelong ax,TPtr phx pha lda par inc a clc adc NewPars jsl W_GetParRec movelong ax,Block2 phx pha lda W_LastP inc a jsl W_GetParRec movelong ax,Block1 sublong Block1,TPtr,s _BlockMove jsl D_BeachBall moveword NewLastP,W_LastP inc W_LastP addlong ParRec1,#W_pBytes,Block2 pushlong Block2 pushlong TPtr sublong ParRec2,Block2,s _BlockMove brl W_AllSet ;It is a special case of a paste within the par JustOne subword [Block1]:#W_BUsed,#W_BHeader+W_TextHeader+1,bytes jeq killscrap pushword par pushword offset lda FBytes asl a addword a,bytes,s addword a,offset,OutOffset jsl W_MakeRoom jsl D_BeachBall rcall W_GetAddr,in=(par:a,offset:x),out=(TPtr:ax) pha pushword par pushword offset pushlong Font1 pushword col1 pushlong Font2 pushword col2 jsl W_WriteFBytes2 subword OutOffset,1:s,OutOffset subword fbytes,s,fbytes addlong fbytes,TPtr,TPtr addlong #W_BHeader+W_TextHeader,Block1,s pushlong TPtr pushlong bytes _BlockMove jsl D_BeachBall pha pushword par addword offset,fbytes,a addword a,bytes,s pushlong Font2 pushword col2 pushlong Font1 pushword col1 jsl W_WriteFBytes2 subword OutOffset,s,OutOffset ;if W_target par was just a cr, use the ruler from copy ; lda BegRul ; beq NoDo ; lda EndRul ; beq NoDo ; ; lda par ; jsl W_GetParRec ; movelong ax,RulRec ; ; pushword #1 ; pushlong [RulRec]:#W_pRulerHand ; jsl W_UnUseRuler ; ; movelong [ParRec1]:#W_pRulerHand,[RulRec]:#W_pRulerHand ; ; bra SkipRulDisp NoDo tool _DisposeHandle,in=([ParRec1]:#W_pRulerHand:l) SkipRulDisp tool _DisposeHandle,in=([ParRec1]:l) jsl D_BeachBall W_AllSet ; lda [ptr] dec a addword a,par,OutPar PLoop jsl D_BeachBall call W_MakeLines,in=(par:w) subword OutPar,par,a cmp #3 bcc NoThow rcall W_GetParRec,in=(par:a),out=(ParRec1:ax) Cmpw [ParRec1]:#W_pAttr,#W_PgBrk beq @1 tool _DisposeHandle,in=([ParRec1]:#W_pLineHand:l) @1 movelong #0,[ParRec1]:#W_pLineHand NoThow inc par cmpw OutPar,par bcs PLoop call W_FindLine,in=(OutPar:w,OutOffset:w),out=(OutLine:w) jsl W_SetFullREct jsl D_BeachBall jsl W_CalcPages jsl D_BeachBall tool _DisposeHandle,in=(handle:l) bra exit ; Memory error occured dispose of scrap. killscrap rcall D_Unlock,in=(handle:ax) call X_DisposeScrap,in=(#WPText:w,Handle:l) exit return ;.................................................................................................... ; addcrtop - add carriage return paragraph entry at the beginning of the scrap. Will return carry set ; if memory errors occured while trying to add carriage return paragraph entry. ; Grow scrap by two paragraph entries in size. addcrtop spacelong addlong #W_pBytes*2,ParRec2,ParRec2 sublong ParRec2,ptr,s pushlong handle jsl D_GrowLHandle sta err pullLong ptr bcc @newpar1 rts ; Get new pointer to first and last paragraph entries. @newpar1 addlong #2,ptr,ParRec1 spacelong lda [ptr] dec a pha pushword #W_pBytes _Multiply addlong s,ParRec1,ParRec2 addlong #W_pBytes,ParRec2,ParRec2 ; Before we munge the scrap lets make sure we will be able to get the new text block we will need if ; not return with memory error. spacelong jsl W_MakeEmptyBlock sta err bcc @domove ; new text block left on stack until pulllong a ; after block move is done. rts ; Move up all paragraph entries one entry block in size. @domove pushlong ParRec1 addlong ParRec1,#W_pBytes,s sublong ParRec2,ParRec1,s _BlockMove ; Fill carriage return paragraph entry default values. Use ruler from carriage return paragraph ; after the page break. pulllong [ParRec1] moveword #W_BHeader,[ParRec1]:#W_pOffset moveword #0,[ParRec1]:#W_pAttr movelong #0,[ParRec1]:#W_pLineHand moveword #1,[ParRec1]:#W_pLastLine movelong [ParRec1]:#W_pRulerHand+W_pBytes+W_pBytes,[ParRec1]:#W_pRulerHand call W_UseRuler,in=(#1:w,[ParRec1]:#W_pRulerHand:l) ; Set default values for empty text block. movelong [ParRec1],Block1 movelong [Block1],TextPtr addword #W_TextHeader+1,[TextPtr]:#W_BUsed,[TextPtr]:#W_BUsed addwl #W_BHeader,TextPtr moveword #W_StandFont,[TextPtr] moveword #W_StandStyle,[TextPtr]:#2 moveword #Black,[TextPtr]:#4 movebyte #cr,[TextPtr]:#W_TextHeader ; Bump the scrap paragraph entries count. Return with carry clear. lda [ptr] inc a sta [ptr] clc rts ;.................................................................................................... ENDP **************************************************************** * W_SplitBlock(par) will make sure that par and par+1 have different blocks W_SplitBlock PROC EXPORT ;Using wpglobals input par:w local ParRec1:l,Blockhand:l,BlockPtr:l local W_offset:w,bytes:w begin CheckAgain lda par jsl W_GetParRec movelong ax,ParRec1 cmpl [ParRec1],[ParRec1]:#W_pBytes bne NoProb movelong [ParRec1],BlockHand movelong [BlockHand],BlockPtr pushword par pushword #W_TextHeader subword [BlockPtr],[ParRec1]:#W_pOffset+W_pBytes,a dec a pha sta bytes jsl W_MakeRoom pushword par pushword #W_TextHeader pushword bytes jsl W_LessRoom brl CheckAgain NoProb return ENDP END