[comp.sys.mac] CopyBits in MPW C 3.0

keith@uw-apl.UUCP (Keith Kerr) (04/12/89)

I am converting some MPW C code from v.2.02 to v.3.0.
The much tighter type-checking is a constant frustration
to my fast and loose programming style.  One particular
problem is with CopyBits.

eg.
PixMapHandle mypixhandle;
.
.
  CopyBits(*mypixhandle, &(((GrafPtr)wind)->portBits),
            &((*mypixhandle)->bounds),&((*mypixhandle)->bounds),
            srcCopy, 0L);

This compiles and works OK in MPW 2.02, but won't compile
in MPW 3.0 because of a type mismatch between formal and actual
parameters in the first argument *mypixhandle.  I've tried
several variations of this, but nothing seems to compile.
The documentation in IM seems to indicate that CopyBits
should take bitmaps and pixmaps with no problem.

Could someone please clue me in as to how to fix this???

Thanks,

wert@toaster.Sun.COM (Robert Scott Comer) (04/13/89)

> The documentation in IM seems to indicate that CopyBits
> should take bitmaps and pixmaps with no problem.

> Could someone please clue me in as to how to fix this???

Here is how you fix that: Look for the definition of CopyBits. See that first
parameter? See its type? Determine what that type is, exactly, then make sure
you pass that type in to CopyBits.

For example, if CopyBits wants a pointer to a BitMap or PixMap, then what you
have looks like it might work, if it wants a handle to one of those you will
have to remove the * from your first argument.

When in doubt, look at the definition. Once you learn that, you are on the
road to learning to help yourself. There is no magic here.

scott comer

pepke@loligo.cc.fsu.edu (Eric Pepke) (04/13/89)

In article <98709@sun.Eng.Sun.COM> wert@sun.UUCP (Robert Scott Comer) writes:
>Here is how you fix that: Look for the definition of CopyBits. See that first
>parameter? See its type? Determine what that type is, exactly, then make sure
>you pass that type in to CopyBits.
>
>For example, if CopyBits wants a pointer to a BitMap or PixMap, then what you
>have looks like it might work, if it wants a handle to one of those you will
>have to remove the * from your first argument.

If you are going to condescend, at least make sure you know what you're
talking about.

OF COURSE CopyBits wants a pointer.  The problem is that the C prototype
wants a pointer to a BitMap, not to a PixMap.  There are a number of ways
of constructing the type cast which can seem to a novice as if they should 
work, but not all of them do.

This code fragment compiles fine under my MPW 3.0 C:

	WindowPtr wind;
	PixMapHandle mypixhandle;

	HLock((Handle) mypixhandle);
	CopyBits(*(BitMap **) mypixhandle, &(wind->portBits),
            &((*mypixhandle)->bounds),&((*mypixhandle)->bounds),
            srcCopy, 0L);
	HUnlock((Handle) mypixhandle);

Notice that the casting of the window to type GrafPtr is not needed.  As 
explained in IM, a WindowPtr is the same as a GrafPtr, and to look in the 
extra fields in a window record, use a WindowPeek type cast.  This is not 
the case for BitMaps and PixMaps, so the cast to BitMap ** is needed.

C and Pascal are becoming more and more alike as time goes on.  :-(

Eric Pepke                                     ARPA:   pepke@gw.scri.fsu.edu
Supercomputer Computations Research Institute  MFENET: pepke@fsu
Florida State University                       SPAN:   pepke@scri
Tallahassee, FL 32306-4052                     BITNET: pepke@fsu

Disclaimer: My employers seldom even LISTEN to my opinions.
Meta-disclaimer: Any society that needs disclaimers has too many lawyers.

beard@ux3.lbl.gov (Patrick C Beard) (04/13/89)

In article <225@uw-apl.UUCP> keith@uw-apl.UUCP (Keith Kerr) writes:
>  CopyBits(*mypixhandle, &(((GrafPtr)wind)->portBits),
>            &((*mypixhandle)->bounds),&((*mypixhandle)->bounds),
>            srcCopy, 0L);
>
>This compiles and works OK in MPW 2.02, but won't compile
>in MPW 3.0 because of a type mismatch between formal and actual
>parameters in the first argument *mypixhandle.
>
>Could someone please clue me in as to how to fix this???

All you  need to do to convince the compiler that this is what you intended,
is to use casts:

	HLock((Handle)mypixhandle);		// since CopyBits can move memory.
	CopyBits((BitMap*)*mypixhandle, &(((GrafPtr)wind)->portBits),
			&((*mypixhandle)->bounds),&((*mypixhandle)->bounds),
  			srcCopy, 0L);
	HUnlock((Handle)mypixhandle);

I hope this helps.

__________________

   Patrick Beard
  PCBeard@lbl.gov
 BSI, Berkeley, CA
___________________

tim@hoptoad.uucp (Tim Maroney) (04/14/89)

In article <225@uw-apl.UUCP> keith@uw-apl.UUCP (Keith Kerr) writes:
>I am converting some MPW C code from v.2.02 to v.3.0.
>The much tighter type-checking is a constant frustration
>to my fast and loose programming style.  One particular
>problem is with CopyBits.
>
>eg.
>PixMapHandle mypixhandle;
>.
>  CopyBits(*mypixhandle, &(((GrafPtr)wind)->portBits),
>            &((*mypixhandle)->bounds),&((*mypixhandle)->bounds),
>            srcCopy, 0L);
>
>This compiles and works OK in MPW 2.02, but won't compile
>in MPW 3.0 because of a type mismatch between formal and actual
>parameters in the first argument *mypixhandle.

Try "CopyBits(*(BitMap **)mypixhandle, ...);"  Incidentally, you
shouldn't be passing a pointer to something stored in a relocatable
handle to CopyBits or any other routine listed as allocating or
moving memory.  Declare a Rect variable and assign the bounds
rectangle to that, then pass a pointer to the variable instead.
-- 
Tim Maroney, Consultant, Eclectic Software, sun!hoptoad!tim
"I see little divinity about them or you.  You talk to me of Christianity
 when you are in the act of hanging your enemies.  Was there ever such
 blasphemous nonsense!" - Shaw, "The Devil's Disciple"

wert@toaster.Sun.COM (Robert Scott Comer) (04/15/89)

Not condescending, really. But face it, he has all the info he needs to
answer this question in a readily accessible form online. It takes less
time to look up the answer to that question than to post the message to
the net! I don't give exact details about CopyBits because my Inside
Mac is at home.

But, his real question isn't about CopyBits!! His real problem is that
he doesn't understand C types and MPW and the Mac. If he understood those
things he wouldn't have to ask. What he really needs is just what I gave
him: directions on how to answer his question himself. This is just the
same as the old proverb: Give a hungry man a meal and he will still be
hungry tomorrow, but give him _____ (fill in the blank with your favorite
enabling technology, like confidence, a shovel, a cow, some seed, etc.)
and he will eat for the rest of his life.

Too many people just answer questions here without thinking about
the person and her context, not from a real need to help them, but
from a need to show that they know the answer.

scott out

pepke@loligo.cc.fsu.edu (Eric Pepke) (04/18/89)

In article <99141@sun.Eng.Sun.COM> wert@sun.UUCP (Robert Scott Comer) writes:
>But, his real question isn't about CopyBits!! His real problem is that
>he doesn't understand C types and MPW and the Mac. If he understood those
>things he wouldn't have to ask. What he really needs is just what I gave
>him: directions on how to answer his question himself.

I think we will have to agree to disagree.  I find the description of
CopyBits on p. 70 of IM V to be incomplete and misleading in this case.

In the past, when a function accepted several different types, the types
were designed in such a way that you don't generally need type casts.
Take as an example GrafPtr, WindowPtr, and DialogPtr.  Most people don't
worry about doing explicit type casts.  This need not mean that they don't
understand type checking; it may simply mean that they do not want to use
a dangerous cast mechanism, which has the effect of overriding type checking.
When handles are used the situation is doubly dangerous, as a misplaced 
cast can lead to an improper handle reference.

In the case of CopyBits, however, no such mechanism was provided, and no
mention was made of the need to cast.  The IM writers IMHO are generally
very careful to warn about known gotchas, so this omission is surprising.

It is true that he, or anybody else, has all the information needed to 
answer the question.  All he had to do was open the appropriate header
files, search for the appropriate prototype, determine that it really
expected a BitMap, search for the declarations of BitMap and PixMap, and
determine that they were not defined in such a way as to obviate explicit
type casts.  This is what I did to satisfy my own curiosity.  He probably 
did in fact figure it out in time, which is why I did not respond to the 
original note.  However, it isn't quite fair to say RTFM when the FM is 
unclear, which is why I responded to your note.

> This is just the
>same as the old proverb: Give a hungry man a meal and he will still be
>hungry tomorrow, but give him _____ (fill in the blank with your favorite
>enabling technology, like confidence, a shovel, a cow, some seed, etc.)
>and he will eat for the rest of his life.

Well, I think that examples are good things, and most people can generalize
from them, which is why I did not give general rules.  I do now:

1) Avoid needless type casts.
2) Take the easiest possible interpretation of the documentation as a first
   cut.  Apple is generally on the side of the programmer, but everyone
   sometimes makes mistakes.
3) When 1 and 2 fail, and type casts are unavoidable, cast as close to the 
   object with the wrong type as possible to avoid losing the cast in a maze 
   of pointers and parentheses.  For example,
        ** (char **) bork
   is preferable to
        * (char *) *bork

All of this is IMHO, of course.  I tend to be very paranoid.  For example,
I try to keep constant expressions on the left side of == just in case I
mess up and type = instead.

>scott out

Eric Pepke                                     ARPA:   pepke@gw.scri.fsu.edu
Supercomputer Computations Research Institute  MFENET: pepke@fsu
Florida State University                       SPAN:   pepke@scri
Tallahassee, FL 32306-4052                     BITNET: pepke@fsu

Disclaimer: My employers seldom even LISTEN to my opinions.
Meta-disclaimer: Any society that needs disclaimers has too many lawyers.

MAC.ROMOS@applelink.apple.com (Ian Hendry) (04/20/89)

In article <8904171804.AA00203@vs03csc.UMD.EDU> russotto@wam.UMD.EDU 
writes:
> I've never had any problem passing dereferenced handles to CopyBits--
> I don't believe it is a routine that moves or purges memory (I believe
> it's temp buffers are on the stack)  Actually, this almost has to be
> for VBL tasks to be able to draw...

WRONG!
Copybits generally does not affect memory, but in some cases it does!  DO 
NOT pass unlocked dereference handles!  There are cases where QD may make 
memory calls during copybits (which would screw up a dereferenced handle) 
and even if I didn't know actual cases I sure wouldn't count on being able 
to pass dereferenced handles and have future compatability!
For example the (very) newly announced 32-Bit extensions to color quckdraw 
have more such cases than the unextended color quickdraw versions, but 
even the older versions do have cases.

Sorry (but not too sorry) if the above is phrased strongly.   :-)

The point is that the cases exist and Apple has said this trap may move 
memory so this is definately a case in which you should follow Apple's 
guidelines.

Ian Hendry
MAC.ROMOS@applelink.apple.com
Make sure my name is in the subject of any Email, or post replies to 
network.
TE: 408-974-4737

Disclaimer:  It was all HIS idea anyway!  Nothing I say reflects anything 
my employer means... or anything I mean for that matter.

darin@Apple.COM (Darin Adler) (04/20/89)

In article <1458@internal.Apple.COM> MAC.ROMOS@applelink.apple.com (Ian Hendry) writes:
> In article <8904171804.AA00203@vs03csc.UMD.EDU> russotto@wam.UMD.EDU 
> writes:
> > I've never had any problem passing dereferenced handles to CopyBits--
> > I don't believe it is a routine that moves or purges memory (I believe
> > it's temp buffers are on the stack)  Actually, this almost has to be
> > for VBL tasks to be able to draw...
>
> Copybits generally does not affect memory, but in some cases it does!  DO 
> NOT pass unlocked dereference handles!  There are cases where QD may make 
> memory calls during copybits (which would screw up a dereferenced handle) 
> and even if I didn't know actual cases I sure wouldn't count on being able 
> to pass dereferenced handles and have future compatability!

Ian is right. You should lock the handles to the pixmaps that you pass to
CopyBits. One of the cases where CopyBits moves memory is where it is the first
stuff drawn to a particular device. In this case, drawing to that device may
cause an inverse table to be built. Again, in future system software, CopyBits
may move memory in even more cases.

If a VBL task is going to draw, it needs to have it's own separate heap.
This is because VBL tasks can run while the contents of the heap are being
moved around. During this time the contents of any relocatable blocks can
be invalid (this includes the regions inherent in a port: necessary for
drawing). Having a separate heap for the VBL gets around this problem, but
is a bit complicated...but if you can think of a good reason to draw from
a VBL task, go ahead. (You'll also need your own A5 world and QuickDraw globals
since A5 might have any random value.)
-- 
Darin Adler, System Software Scapegoat, Apple Computer
	Internet: darin@Apple.com
	UUCP: {nsc,sun}!apple!darin