Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: More Macintosh Toolbox /
Chapter 2 - Scrap Manager / Using the Scrap Manager


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;
The DoCutOrCopyCmd procedure first determines the type of window that is frontmost. If the frontmost window is a document window, DoCutOrCopyCmd uses 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'. The DoCutOrCopyCmd procedure uses another application-defined routine, MyGetSelection, to return the current selection in a particular format. DoCutOrCopyCmd then calls the ZeroScrap function to clear the contents of the scrap. After calling ZeroScrap, DoCutOrCopyCmd calls PutScrap, specifying the length of the data, a pointer to the data, and identifying the scrap format type as 'SURF'. DoCutOrCopyCmd then uses the MyGetSelection routine again, this time to return the current selection in the 'TEXT' format type. DoCutOrCopyCmd calls PutScrap to 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, DoCutOrCopyCmd uses the MyGetSelection routine to return the current selection using the 'PICT' format type. After calling ZeroScrap, DoCutOrCopyCmd calls PutScrap to write the data to the scrap, specifying a pointer to the data and identifying the scrap format type as 'PICT'.

Finally, if DoCutOrCopyCmd was called as a result of the user performing a cut operation, DoCutOrCopyCmd deletes the selection from the current document.

If the frontmost window is a dialog box, DoCutOrCopyCmd uses the Dialog Manager's DialogCut (or DialogCopy) procedure to write the selected data to the scrap.

Note that you should always call ZeroScrap before writing data to the scrap. If you write multiple formats to the scrap, call ZeroScrap once 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 (or TECopy) instead of ZeroScrap and PutScrap. 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-defined DoCutOrCopyCmd procedure 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 variable gScrapNewData to 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 the gScrapNewData global variable to TRUE. If the user chooses Paste and gScrapNewData is TRUE, 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 DoCutOrCopyCmd procedure resets the gScrapNewData global variable to FALSE.

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. The DoSuspendResumeEvent procedure first gets a pointer to the front window using the Window Manager function FrontWindow. It then examines bit 0 of the message field 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 DoSuspendResumeEvent procedure calls the application-defined MyConvertScrap procedure to copy the contents of its private scrap to the scrap. (See Listing 2-7 on page 2-27 for the MyConvertScrap procedure.) It then sets the private global flag gInBackground to TRUE to 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 routine MyHideClipboardWindow to hide the Clipboard window if it's currently showing.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
6 JUL 1996