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: Programmer's Guide to MacApp / Part 2 - Working With MacApp
Chapter 27 - Working With Streams


Recipes--Streams

The recipe and sample code in this section demonstrate how to use a handle stream.

Recipe--Using a Handle Stream to Write Text to a Handle

The Calc sample application implements a spreadsheet view with rows and columns of cells. Calc supports publish and subscribe, and a user can select a group of cells and publish the data they contain. When a user publishes cell data, the Calc document object calls a method of the spreadsheet view (TCellsView::DesignatorAsTEXT) to write the text from the designated cells to a handle.

The DesignatorAsTEXT method provides a good example of using a stream to write data to a handle. The calling method passes a designator that identifies a group of one or more cells. The DesignatorAsTEXT method extracts text from the cells, uses a handle stream to write the text to a handle, and returns the handle. The calling method can use the handle (and its stored text) as required, but must be sure to free the handle when it has finished with it.

To use a handle stream to write text data to a handle, you perform these steps:

  1. Create a handle.
  2. Create a handle stream and initialize it with the handle you created.
  3. Call methods of the stream to write your text data to the stream.
  4. Free the handle stream.

The sample code shown in this recipe is from the Calc application.

Create a Handle

Creating a handle is a standard Macintosh operation. The DesignatorAsTEXT method creates a handle with an arbitrary initial size of 100. A handle stream will increase the size of its handle as necessary.

Handle textHandle;
textHandle = NewPermHandle(100);

Create and Initialize a Handle Stream

When you initialize a handle stream, you pass it two items: a reference to a handle and a value that indicates the size by which the handle should be grown. When more space is needed, the handle stream will increase its handle size by the amount needed or by the specified growth size, whichever is larger.

THandleStream * aHandleStream;
aHandleStream = new THandleStream;
aHandleStream->IHandleStream(textHandle, 10);

Write Text Data to the Handle Stream

The DesignatorAsTEXT method performs some additional operations to determine which cells should be examined and to set up an iterator to iterate over those cells. It then executes a loop to write the text from each cell to the handle stream. The complete code for DesignatorAsTEXT is shown on the following page.

Handle TCellsView::DesignatorAsTEXT(TDesignator* aDesignator)
{
   CRect       bounds;
   Handle      textHandle;
   THandleStream * aHandleStream;
   CStr255     theString;
   RgnHandle   aRgn;

   textHandle = NewPermHandle(100);
   aHandleStream = new THandleStream;
   aHandleStream->IHandleStream(textHandle, 10);
   aRgn = ((TRegionDesignator *)(aDesignator))->fDesignation;
   bounds = (*aRgn)->rgnBBox;
   bounds.bottom--;
   bounds.right--;
   CCellIterator iter(this, bounds[topLeft], bounds[botRight], kIterateForward,
                  kIterateForward, CCellIterator::kIterateRowMajor);
   for (GridCell aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
   {
      SignedByte aChar;
      // Write out the cell's contents if the cell is included and it exists.
      if (PtInRgn(aCell, aRgn) && fCalcDocument->CellExists(aCell.v, aCell.h))
      {
         fCalcDocument->GetCell(aCell.v, aCell.h)->GetValueAsString(theString);
         // Use WriteBytes instead of WriteString to avoid writing length byte.
         aHandleStream->WriteBytes(&theString[1], theString.Length());
      }
      // Write out the delimiter: tab or carriage return.
      if (aCell.h == bounds.right)
         aChar = 0x0D;
      else
         aChar = 0x09;
      aHandleStream->WriteBytes(&aChar, sizeof(SignedByte));
   }
   aHandleStream->Free();
   return textHandle;
}  // TCellsView::DesignatorAsTEXT\

Free the Handle Stream

The DesignatorAsTEXT method frees the handle stream, which frees the stream object itself but not its handle, then returns the handle.

aHandleStream->Free();
return textHandle;
The calling routine is responsible for freeing the handle when it has finished with it.

Using the Handle Data

Once you have written data to a handle, you can use the handle just as you would any other handle variable. For example, you can use a file stream to write the handle to a document; you can also use a file stream to read the handle back from the document.

The Calc application uses this approach to read and write cell data. For writing, it writes cell data to a handle (with the DesignatorAsTEXT method shown above), then uses a file stream to write the data to a document. For reading the data, it uses the DoReadTEXT method to read the handle from a file stream and then extract the data from the handle.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
25 JUL 1996