Important: The information in this document is obsolete and should not be used for new development.
Putting Data in the Scrap
Your application should write data to the scrap (or to its own private scrap) whenever the user chooses the Cut or Copy command and the document the user is working with contains a selection. In addition, if your application uses a private scrap, your application must copy the contents of its private scrap to the scrap upon receiving a suspend event. The next sections explain how to perform these tasks.Handling the Cut Command
When the user chooses the Cut command and the document the user is working with contains a selection, your application should remove the data from the selection and save the data (either in the scrap or in your application's private scrap).The SurfWriter application doesn't use a private scrap; whenever the user performs a cut operation, SurfWriter writes the current selection to the scrap. The SurfWriter application does define its own private scrap format type and writes this format to the scrap, along with one of the standard scrap formats. Listing 2-1 shows SurfWriter's routine for handling the Cut command (it also uses this routine for the Copy command).
Listing 2-1 Writing data to the scrap
PROCEDURE DoCutOrCopyCmd (cut: Boolean); VAR window: WindowPtr; windowType: Integer; isText: Boolean; ptrToScrapData: Ptr; length, myLongErr: LongInt; BEGIN window := FrontWindow; windowType := MyGetWindowType(window); IF windowType = kMyDocWindow THEN BEGIN ptrToScrapData := NewPtr(kDefaultSize); isText := MyIsSelectionText; IF isText THEN {selection contains text} BEGIN MyGetSelection('SURF', ptrToScrapData, length); myLongErr := ZeroScrap; myLongErr := PutScrap(length, 'SURF', ptrToScrapData); IF myLongErr <> noErr THEN DoError(myLongErr); MyGetSelection('TEXT', ptrToScrapData, length); myLongErr := PutScrap(length, 'TEXT', ptrToScrapData); IF myLongErr <> noErr THEN DoError(myLongErr); END ELSE {selection contains graphics} BEGIN MyGetSelection('PICT', ptrToScrapData, length); myLongErr := ZeroScrap; myLongErr := PutScrap(length, 'PICT', ptrToScrapData); IF myLongErr <> noErr THEN DoError(myLongErr); END; DisposePtr(ptrToScrapData); IF cut THEN MyDeleteSelection; END ELSE IF windowType <> kNIL THEN BEGIN {window is a dialog box} IF cut THEN DialogCut(window) ELSE DialogCopy(window); END; END;TheDoCutOrCopyCmdprocedure first determines the type of window that is frontmost. If the frontmost window is a document window,DoCutOrCopyCmduses another application-defined routine,MyIsSelectionText, to determine whether the current selection contains text or graphics. If the selection contains only text, SurfWriter writes the data to the scrap using two formats: its own private format ('SURF') and the standard format'TEXT'. TheDoCutOrCopyCmdprocedure uses another application-defined routine,MyGetSelection, to return the current selection in a particular format.DoCutOrCopyCmdthen calls theZeroScrapfunction to clear the contents of the scrap. After callingZeroScrap,DoCutOrCopyCmdcallsPutScrap, specifying the length of the data, a pointer to the data, and identifying the scrap format type as'SURF'.DoCutOrCopyCmdthen uses theMyGetSelectionroutine again, this time to return the current selection in the'TEXT'format type.DoCutOrCopyCmdcallsPutScrapto write the data to the scrap, specifying a pointer to the data and identifying the scrap format type as'TEXT'.If the selection contains a picture,
DoCutOrCopyCmduses theMyGetSelectionroutine to return the current selection using the'PICT'format type. After callingZeroScrap,DoCutOrCopyCmdcallsPutScrapto write the data to the scrap, specifying a pointer to the data and identifying the scrap format type as'PICT'.Finally, if
DoCutOrCopyCmdwas called as a result of the user performing a cut operation,DoCutOrCopyCmddeletes the selection from the current document.If the frontmost window is a dialog box,
DoCutOrCopyCmduses the Dialog Manager'sDialogCut(orDialogCopy) procedure to write the selected data to the scrap.Note that you should always call
ZeroScrapbefore writing data to the scrap. If you write multiple formats to the scrap, callZeroScraponce before you write the first format to the scrap.You should always write data to the scrap in your application's preferred order
of formats. For example, SurfWriter's preferred format for text data is its own private format ('SURF'), so it writes that format first and then writes the standard format'TEXT'.If your application uses TextEdit in its document windows, then use the TextEdit routine
TECut(orTECopy) instead ofZeroScrapandPutScrap. See Listing 2-8 on page 2-29 for an application-defined routine that uses TextEdit routines to help handle the Cut and Copy commands.If your application uses a private scrap, then copy the selected data to your private scrap rather than to the scrap. For example, the SurfPaint application uses a private scrap. Listing 2-2 shows SurfPaint's application-defined routine that handles the Cut command by writing the selected data to its private scrap.
Listing 2-2 Writing data to a private scrap
PROCEDURE DoCutOrCopyCmd (cut: Boolean); VAR window: WindowPtr; windowType: Integer; BEGIN window := FrontWindow; windowType := MyGetWindowType(window); IF windowType = kMyDocWindow THEN BEGIN MyWriteDataToPrivateScrap; {reset gScrapNewData to indicate that this app's private } { scrap now contains the most recent data} IF gScrapNewData THEN gScrapNewData := FALSE; IF cut THEN MyDeleteSelection; END ELSE IF windowType <> kNil THEN BEGIN {window is a dialog window} IF cut THEN DialogCut(window) ELSE DialogCopy(window); END; END;The application-definedDoCutOrCopyCmdprocedure shown in Listing 2-2 calls another application-defined procedure,MyWriteDataToPrivateScrap, to write the data in the current selection to the application's private scrap. SurfPaint uses the application-defined global variablegScrapNewDatato indicate when data should be read from the scrap instead of its own private scrap as a result of the user choosing the Paste command. Upon receiving a resume event, if the contents of the scrap have changed, SurfPaint sets thegScrapNewDataglobal variable toTRUE. If the user chooses Paste andgScrapNewDataisTRUE, SurfPaint reads the scrap to get the data to paste; otherwise SurfPaint reads its own private scrap to get the data to paste.If the user chooses Cut or Copy before the next Paste command, SurfPaint writes the newly selected data to its private scrap, eliminating the need to read the previous contents of the scrap, and thus the
DoCutOrCopyCmdprocedure resets thegScrapNewDataglobal variable toFALSE.Handling the Copy Command
When the user chooses the Copy command and the document the user is working with contains a selection, your application should copy the selected data (without deleting it) and save the copied data (either in the scrap or in your application's private scrap). See Listing 2-1 on page 2-16, Listing 2-2 on page 2-18, and Listing 2-8 on page 2-29 for application-defined routines that handle the Copy command.Handling Suspend Events
As previously described, if your application uses a private scrap, your application must copy the contents of its private scrap to the scrap upon receiving a suspend event. In addition, if your application supports the Show Clipboard command, it should hide the Clipboard window if it's currently showing (because the contents of the scrap may change while your application yields time to another application).Listing 2-3 shows SurfPaint's routine that responds to suspend events (and resume events).
Listing 2-3 Copying data from the scrap in response to suspend events
PROCEDURE DoSuspendResumeEvent (event: EventRecord); VAR currentFrontWindow: WindowPtr; BEGIN currentFrontWindow := FrontWindow; IF (BAnd(event.message, resumeFlag) <> 0) THEN BEGIN {it's a resume event; } END { handle as shown in Listing 2-6} ELSE BEGIN {it's a suspend event} {copy private scrap to the scrap} MyConvertScrap(kPrivateToClipboard); gInBackground := TRUE; {deactivate front window} DoActivate(currentFrontWindow, NOT gInBackground, event); MyHideClipboardWindow; {hide Clipboard window if showing} MyHideFloatingWindows; {hide any floating windows} END; END;Listing 2-3 shows a procedure that responds to suspend and resume events. TheDoSuspendResumeEventprocedure first gets a pointer to the front window using the Window Manager functionFrontWindow. It then examines bit 0 of themessagefield of the event record to determine whether the event is a suspend or resume event. See Listing 2-6 on page 2-25 for details on handling resume events.For suspend events, the
DoSuspendResumeEventprocedure calls the application-definedMyConvertScrapprocedure to copy the contents of its private scrap to the scrap. (See Listing 2-7 on page 2-27 for theMyConvertScrapprocedure.) It then sets the private global flaggInBackgroundtoTRUEto indicate that the application is in the background. It calls another application-defined routine to deactivate the application's front window. It also calls the application-defined routineMyHideClipboardWindowto hide the Clipboard window if it's currently showing.
 
  
  
 