[comp.sys.mac] Help: Using CopyBits for Update

sam@neoucom.UUCP (Scott A. Mason) (05/08/89)

I need some help from some of you more experienced Mac programmers.
Although I am well versed in C, I am just starting to program in the
Macintosh environment.

I have a window which I use QuickDraw routines to draw characters.  (Not
a text edit window, that is)  I am have difficulties responding to an
update event.  I have IM volumes and several different books, but none of
them sufficiently covers the use of an offscreen buffer to store window
info for updating.  

How does one set up an offscreen buffer so that CopyBits may be used to 
refresh the window when responding to an update event? 
-- 
--------------------------------------------------------------------------------
"If it ain't broke, don't fix it," and certainly don't blame me.
UUCP:  {pitt, scooter, hal, cwjcc}!neoucom!sam    INTERNET:  sam@neoucom.UUCP
Scott A. Mason, Coordinator of Systems Operations, NEOUCOM

ksitze@nmsu.edu (Kevin Sitze) (05/10/89)

In article <sam@neoucom.UUCP's message of 8 May 89 04:17:52 GMT>
>I have a window which I use QuickDraw routines to draw characters.  (Not
>a text edit window, that is)  I am have difficulties responding to an
>update event.  I have IM volumes and several different books, but none of
>them sufficiently covers the use of an offscreen buffer to store window
>info for updating.  
>
>How does one set up an offscreen buffer so that CopyBits may be used to 
>refresh the window when responding to an update event?

This is really a rather simple procedure.  The idea is to draw into an
offscreen port and then CopyBits the wanted information to the desired
window.  To setup an offscreen port for drawing, you can do something
like this...

In Pascal (LSP):

Function SetupPort : GrafPtr;
var
  tmpPort, myPort : GrafPtr;
begin
  GetPort(tmpPort);
    { Need to allocate memory for the port }
  myPort := GrafPtr(NewPtr(sizeof(GrafPort));
    { -- Error checking for nil pointer goes here -- }
    { Create the internal structures for the port }
  OpenPort(myPort);
    { Now we need to set aside enough memory to draw into }
  with myPort^.portBits do
    begin
      baseAddr := NewPtr(rowBytes * (bounds.bottom - bounds.top));
        { -- Error checking for nil pointer goes here -- }
        { Don't need to initialize any of the rest of the fields in }
        { the port because Quickdraw has done all we need already. }
    end;
  { And return the resulting port, voila, an offscreen graph port! }
  SetPort(tmpPort);
  SetupPort := myPort;
end;

or, for them (LS)C buffs...

#define myBM myPort->portBits
GrafPtr SetupPort()
{
    GrafPtr tmpPort;
    register GrafPtr myPort;

    GetPort(&tmpPort);
    myPort = (GrafPtr) NewPtr(sizeof(GrafPort));
        /* -- Error checking for nil pointer goes here -- */
        /* Create the internal structures for the port */
    OpenPort(myPort);
        /* Now we need to set aside enough memory to draw into */
    myBM.baseAddr = NewPtr(myBM.rowBytes * (myBM.bounds.bottom -
        myBM.bounds.top)); 
        /* -- Error checking for nil pointer goes here -- */
        /* And return the resulting port, voila, an offscreen graph port! */
    SetPort(tmpPort);
    return myPort;
}
#undef myBM

There are several problems with the program as it stands above.  1) it
does not have any error conditions.  2) It eats up about 6K of the
heap everytime it's called (or more if your doing color, but if that's
the case, you'll _need_ to look at Macintosh Technote #120)

Notice that I saved the current port on entry, this is because I
didn't really want SetupPort to change my current graph port.  If you
don't care, you can remove these lines (but you may never know when
you may need them, I spent several hours tracking down a single
missing SetPort once...not a pleasant experience.)

You can save memory by passing a window to the procedure and then
resizing the port to the window size.  If you do this though, you have
to resize the port everytime you resize the window, something of a
bother.  Enough of this, let's describe how to draw, etc.

The procedure to draw into the newly created port may look something
like this (in Pascal):

Procedure DrawInMyPort( port : GrafPtr );
var
  tmpPort : GrafPtr;
begin
  GetPort(tmpPort);
  SetPort(port);
    { various Quickdraw calls here }
  SetPort(tmpPort);
end;

And in C...

DrawInMyPort(port)
GrafPtr port;
{
    GrafPtr tmpPort;

    GetPort(&tmpPort);
    SetPort(port);
        /* various Quickdraw calls here */
    SetPort(tmpPort);
}

Pretty easy huh?  The way the port is setup, you have the entire
'screen' to draw into, we'd have to do a few more calls if the window
are 'larger' than the screen (e.g. paint programs).  Finally, we want
to do an update event, drawing from the offscreen port to a window:

Procedure UpdateWind( wind : WindowPtr; port : GrafPtr );
var
  tmpPort;
begin
  GetPort(tmpPort);
  SetPort(wind);
  BeginUpdate(wind);
  CopyBits(port^.portBits, wind^.portBits, port^.portRect,
    wind^.portRect, srcCopy, nil);
  EndUpdate(wind);
  SetPort(tmpPort);
end;

or

#define NIL (0L)
UpdateWind(wind, port);
WindowPtr wind;
GrafPtr port;
{
    GrafPtr tmpPort;

    GetPort(&tmpPort);
    SetPort(wind);
    BeginUpdate(wind);
    CopyBits(&port->portBits, &wind->portBits, &port->portRect,
        &wind->portRect, srcCopy, NIL);
    EndUpdate(wind);
    SetPort(tmpPort);
}

These are all pretty much basic routines here but they should work.
If you have any more questions, you might refer to the Macintosh
technical notes.  (You might be able to find the most recently
distributed tn's on comp.mac.sources (comp.sources.mac?))
Specifically, TN#120 (which I know was uploaded recently)  Hope this
helps!

				-Kelesi
--
------------------------------------+-------------------------------
From the Macintosh of: Kevin Sitze  | Disclamer: Who the heck needs
                                    |   a disclamer?  After all, Dan
EMail: ksitze%NMSU.edu              |   Quayle doesn't.
SMail: 601 S. Melendres             +-------------------------------
       Las Cruces, NM  88005        | "We have the answers, the
------------------------------------+  trouble lies in finding the
"The difference between intelligence|  questions..."
and stupidity is that intelligence  | "The information is there,
has a limit."           - anonymous |  finding it is another story."
The dolt confuses you -- more --    |	   	    - Any consultant
------------------------------------+-------------------------------