From: pottier@clipper.ens.fr (Francois Pottier)
Subject: csmp-digest-v3-055
Date: Thu, 8 Sep 1994 18:50:13 +0200 (MET DST)

C.S.M.P. Digest             Thu, 08 Sep 94       Volume 3 : Issue 55
 
Today's Topics:
 
        Clover+. interrupt?~
        Standard C Libraries: use them?
        Summary of 'Safe Save' problem - IM:Files flawed!
        What Happens in the Resource Fork
        Why does NewGWorld do this?
        Won't strange windows come in my layer?



The Comp.Sys.Mac.Programmer Digest is moderated by Francois Pottier
(pottier@clipper.ens.fr).
 
The digest is a collection of article threads from the internet newsgroup
comp.sys.mac.programmer.  It is designed for people who read c.s.m.p. semi-
regularly and want an archive of the discussions.  If you don't know what a
newsgroup is, you probably don't have access to it.  Ask your systems
administrator(s) for details.  If you don't have access to news, you may
still be able to post messages to the group by using a mail server like
anon.penet.fi (mail help@anon.penet.fi for more information).
 
Each issue of the digest contains one or more sets of articles (called
threads), with each set corresponding to a 'discussion' of a particular
subject.  The articles are not edited; all articles included in this digest
are in their original posted form (as received by our news server at
nef.ens.fr).  Article threads are not added to the digest until the last
article added to the thread is at least two weeks old (this is to ensure that
the thread is dead before adding it to the digest).  Article threads that
consist of only one message are generally not included in the digest.

The digest is officially distributed by two means, by email and ftp.

If you want to receive the digest by mail, send email to listserv@ens.fr
with no subject and one of the following commands as body:
    help		                Sends you a summary of commands
    subscribe csmp-digest Your Name	Adds you to the mailing list
    signoff csmp-digest			Removes you from the list
Once you have subscribed, you will automatically receive each new
issue as it is created.

The official ftp info is //ftp.dartmouth.edu/pub/csmp-digest.
Questions related to the ftp site should be directed to
scott.silver@dartmouth.edu. Currently no previous volumes of the CSMP
digest are available there.

Also, the digests are available to WAIS users.  To search back issues
with WAIS, use comp.sys.mac.programmer.src. With Mosaic, use
http://www.wais.com/wais-dbs/comp.sys.mac.programmer.html.


-------------------------------------------------------

>From arthur_babitz@mentorg.com (Arthur Babitz)
Subject: Clover+. interrupt?
Date: Tue, 23 Aug 1994 13:51:08 -0800
Organization: Mentor Graphics Corp., Wilsonville, OR., USA

I've been trying unsuccessfully to implement a "clover+." interrupt for a
compute intensive part of an application.  I won't bore you with a list of
things I've tried which don't work, but can someone point me in the right
direction?  Seems like there must be a standard, simple solution to this
problem.

Thanks!

+++++++++++++++++++++++++++

>From timothys@hood.uucp (Timothy Sherburne)
Date: 24 Aug 94 16:19:46 GMT
Organization: University of Portland

arthur_babitz@mentorg.com (Arthur Babitz) writes:

>I've been trying unsuccessfully to implement a "clover+." interrupt for a
>compute intensive part of an application.  I won't bore you with a list of
>things I've tried which don't work, but can someone point me in the right
>direction?  Seems like there must be a standard, simple solution to this
>problem.

>Thanks!

The trick is to check for a cmd-. (the "clover" key is usually called the command key) in your event loop.  Or you could implement a GetKeys filter.

Here's a snippet using WaitNextEvent that returns a "true" if cmd-. is detected:

Boolean CheckForCmdPeriod (void)
{
	EventRecord	theEvent;
	char		key;
	Boolean		result = false;
	
	// Wait for an event...
	
	if (WaitNextEvent (keyDownMask, &theEvent, kMaxSleep, nil))
	{
		// Get the ASCII value of the key from the event record... 
		
		key = theEvent.message & charCodeMask;
		
		// If the key value is equal to that of the period key and
		// the command modifier key is also being held down, then
		// set result to true...
	
		if ((theEvent.modifiers & cmdKey) && key == '.')   // cmd-. 
			result = true;
	}
	
	return result;
}

Here's a snippet using the "GetKeys" toolbox call:

Boolean CheckForCmdPeriod (void)
{
	KeyMap		keys;

	// Check to see if the user has pressed command-period keys...
		
	GetKeys (keys);
	if(keys [1] & 0x00800000)	// command
	{
		GetKeys (keys);
		if(keys[1] & 0x00008000)	// . (period)
		{
			FlushEvents (mDownMask + mUpMask, 0);
			return true;
		}
	}
	else
		return false;
}

The GetKeys call will catch cmd-. that is intended for anyone, so use it sparingly.  It will also not filter the cmd-.



Don't Panic,


t
-- 
  | Timothy Sherburne                    |               Software Engineer |
  | Internet:  timothys@uofport.edu      |       Prometheus Products, Inc. |
  | AppleLink: D6164@applelink.apple.com |                  1-800-477-3473 |
*All comments are my own and in no way represent those of Prometheus Products*

+++++++++++++++++++++++++++

>From dshayer@netcom.com (David Shayer)
Date: Wed, 24 Aug 1994 18:04:50 GMT
Organization: NETCOM On-line Communication Services (408 261-4700 guest)

Arthur Babitz (arthur_babitz@mentorg.com) wrote:
: I've been trying unsuccessfully to implement a "clover+." interrupt for a
: compute intensive part of an application.  I won't bore you with a list of
: things I've tried which don't work, but can someone point me in the right
: direction?  Seems like there must be a standard, simple solution to this
: problem.

The simplest solution is to simply call WaitNextEvent every so often, 
checking for keydown events of cmd-period.  This is polling, not 
interrupt based.  But that's the correct way to do it on a Mac.

David


+++++++++++++++++++++++++++

>From rhn@waltz.engr.sgi.com (Ron Nicholson)
Date: Thu, 25 Aug 1994 02:02:12 GMT
Organization: Silicon Graphics, Inc., Mountain View, CA

In article <timothys.777745186@hood>,
Timothy Sherburne <timothys@hood.uucp> wrote:
>arthur_babitz@mentorg.com (Arthur Babitz) writes:
>
>>I've been trying unsuccessfully to implement a "clover+." interrupt for a
>>compute intensive part of an application.  I won't bore you with a list of
>>things I've tried which don't work, but can someone point me in the right
>>direction?  Seems like there must be a standard, simple solution to this
>>problem.
(snip)
>Here's a snippet using WaitNextEvent that returns a "true" if cmd-. ...
>
(snip)

A program has to call WaitNextEvent to cleanly check for a keyboard
abort (command-period).  I tried this in an inner loop of a compute
intensive application and it slowed down the computation noticeably.
I had to figure out a way to poll often enough to not make the user
interface seem sluggish, while slowing calculation down minimally.

What I now do is to is this:

First I install a VBL task whose only function is to increment a global
variable.  That gives me a tickcount variable that can be read without
a function call.  You can also use the TickCount() access function.
(Or you can just use the lowmem global Ticks at $016A if you aren't
strictly following Apple's guidelines.  Would I do that? :-)

In my inner loop I have code similar to:	/* in pseudo code */

int ComputeIntensiveFunction(parameters ...)
{
  ...
  volatile long int	*myTickCountPtr;
  long int		CheckNow;
  int			LocalCounter;		/* a local variable */

  myTickCountPtr = &some_tickcount_global; 	/* point at tickcount */
  CheckNow = *myTickCountPtr + 6;		/* every 10th of a second */
  LocalCounter = 25;
  ...

  for (i=1,i<1000000000;i++) {

    ...  /* compute intensive inner loop stuff that goes on forever */

    if (--LocalCounter <= 0) {
      if (*myTickCountPtr >= CheckNow) {
	flag = CheckForAbortEvent();	/* wrapper for WaitNextEvent */
	if (flag)
  	  return(kSomeErrorCode);	/* abort calculation	*/
					/* or alternatively just break */
	else
	  CheckNow = *myTickCountPtr + 6;
      }
      LocalCounter = 25;		/* or some such value	*/
    }
  }
  ...
  return(kFinishedCalculating);
}

Every time through the loop, the code does one local variable decrement
and compare.  Every 25th time, the code does one global variable
(probably uncached and thus slower) load and compare.  Every 10th of a
second, the code polls the event queue for abort, application switches, etc.

The "6" and "25" are just example values.  You might want to choose the
initial loop counter value based on application tuning and the processor
speed of the Mac on which the application is running.

- -
Ronald H. Nicholson, Jr.	rhn@engr.sgi.com, rhn@netcom.com, N6YWU
#include <canonical.disclaimer> 	// I speak only for myself, etc.

+++++++++++++++++++++++++++

>From radixinc@aol.com (RadixInc)
Date: 25 Aug 1994 01:11:10 -0400
Organization: America Online, Inc. (1-800-827-6364)

In article <Cv2Izo.Ao1@odin.corp.sgi.com>, rhn@waltz.engr.sgi.com (Ron
Nicholson) writes:

<<
A program has to call WaitNextEvent to cleanly check for a keyboard
abort (command-period).  I tried this in an inner loop of a compute
intensive application and it slowed down the computation noticeably.
I had to figure out a way to poll often enough to not make the user
interface seem sluggish, while slowing calculation down minimally.
>>

A program has to call WaitNextEvent to cleanly do a lot of things. If you
aren't checking events you are hogging the machine and not letting other
apps have time. And what do you mean "not make the user interface seem
sluggish?" What user interface do you have when you aren't checking for
events?

<<
First I install a VBL task whose only function is to increment a global
variable.  That gives me a tickcount variable that can be read without
a function call.  You can also use the TickCount() access function.
(Or you can just use the lowmem global Ticks at $016A if you aren't
strictly following Apple's guidelines.  Would I do that? :-)
>>

This is silly. Just call TickCount(), or if you have to, just look at
Ticks. You are overly worried about performance, yet you install a VBL
task that does the same thing as an existing VBL task (how do you think
Ticks gets updated in the first place?). You can use any DOCUMENTED
low-memory globals, like Ticks, without getting in trouble. Certainly
given the choice between that and installing a VBL, DTS would advise the
former.

As for the code sample, why not call EventAvail periodically with an event
mask that ignores events you don't care about? That way you won't end up
with an event loop inside your compute-intensive loop and (presumably)
another one in your main program. (DTS will certainly frown on calling
WaitNextEvent from more than one place in your program). And rather than
using Ticks and the local counter, use a modulo calculation on your loop
variable; e.g. check for an event every 10,000 iterations or so.

Make it work first, optimize the slow parts later [after identifying the
slow parts].

Gregory Jorgensen
Radix Consulting Inc.

+++++++++++++++++++++++++++

>From rhn@waltz.engr.sgi.com (Ron Nicholson)
Date: Thu, 25 Aug 1994 17:31:16 GMT
Organization: Silicon Graphics, Inc., Mountain View, CA

In article <33h95e$ekn@search01.news.aol.com>,
RadixInc <radixinc@aol.com> wrote:
>
>As for the code sample, why not call EventAvail periodically with an event
>mask that ignores events you don't care about? That way you won't end up
>with an event loop inside your compute-intensive loop and (presumably)
>another one in your main program. (DTS will certainly frown on calling
>WaitNextEvent from more than one place in your program). And rather than
>using Ticks and the local counter, use a modulo calculation on your loop
>variable; e.g. check for an event every 10,000 iterations or so.
>

You're right, EventAvail is a better choice for polling.  But what's
wrong with calling WNE from more than one place?  WNE has an eventmask
also.  I just get the events that I want to abort my loop, allow WNE to
put the program in the background, etc.

Using a modula on the loop count is very bad.  The difference in speed
between a Plus and a 8100/80 is enormous, especially on FP stuff.
Either you will poll much to seldom on slow machines.  Or waste a lot
of time in WNE on fast machines.  That's assuming that the time through
the loop is deterministic.  If it isn't, the Mac GUI could get jerky
suddenly if the modulo is set wrong on any machine.

My goal was to poll WNE at the same rate on slow and fast machines so
that the Mac GUI never feels jerky (menus drop promptly, etc.).  Around
the neighborhood of 15 times a second feels about right.  This works
for me and doesn't slow down a program that spends a lot of time doing
FFT's more than 1%.

- -
Ronald H. Nicholson, Jr.	rhn@engr.sgi.com, rhn@netcom.com, N6YWU
#include <canonical.disclaimer> 	// I speak only for myself, etc.

+++++++++++++++++++++++++++

>From radixinc@aol.com (RadixInc)
Date: 25 Aug 1994 15:29:10 -0400
Organization: America Online, Inc. (1-800-827-6364)

I understand that the overhead of making the WNE toolbox call and polling
for events is time consuming, especially if you are trying to squeeze the
most performance out of a loop. Lots of programs just put up the "watch"
cursor and ignore all events while they do their computation. This is
considered bad etiquette, because WNE does more than just feed events to
your app. It is the only way to let other processes have time. Those other
processes may just be apps sitting there waiting for user input, in which
case it doesn't matter, but they may be important background processes,
such as network software or background printing.

Because so many programs are rude about giving up time with WNE, some
developers have gone the route of installing VBL or Time Manager tasks to
make sure they get time, and this is even worse.

If your method of calling WNE every 10 ticks works, and you can live with
the potential problems of having two WNE calls in your program, great. I
still think you'd be better off calling EventAvail with an event mask, so
if an event does show up you can exit your loop and let your "main" even
loop handle the event (EventAvail doesn't dequeue the event). You can use
a mask to just look for keyboard events, so mouse events and so on are
ignored (but remain in the even queue).

Also keep in mind that, depending on the speed of the Mac you are running
on, events don't live all that long. The event queue only holds 20 events,
and if you aren't removing them with WNE the old events will be lost. That
means you have to poll for events fast enough to catch them before they
are lost. User-interface events will happen much less frequently than
every 10 ticks, but network events may happen very fast on certain Macs.


Gregory Jorgensen
Radix Consulting Inc.

+++++++++++++++++++++++++++

>From wilkins@jarthur.cs.hmc.edu (Mark Wilkins)
Date: 25 Aug 1994 21:03:07 GMT
Organization: Harvey Mudd College, Claremont CA

In article <33ire6$s4i@search01.news.aol.com>,
RadixInc <radixinc@aol.com> wrote:
>If your method of calling WNE every 10 ticks works, and you can live with
>the potential problems of having two WNE calls in your program, great. I
>still think you'd be better off calling EventAvail with an event mask...


  What possible problems could be caused by having multiple calls to
WaitNextEvent in an application, especially if the purpose is to check for
interruption of a time-consuming process?

  An application which doesn't try to do nifty things like threading will
usually limit user input during a time-consuming processing task to that
which could interrupt the task or that which needs to be passed on to the OS
such as a click in another app's window.

  In other words, why should I care if I'm throwing away events which don't
consist of a command period or mouse click when those are the only two forms
of interaction my application will entertain when it's chugging away?  That
is, assuming I'm only throwing away events directed at my application...

  I'm just not sure I see the issue.

-- Mark Wilkins

+++++++++++++++++++++++++++

>From radixinc@aol.com (RadixInc)
Date: 26 Aug 1994 00:11:08 -0400
Organization: America Online, Inc. (1-800-827-6364)

In article <33j0ub$eip@jaws.cs.hmc.edu>, wilkins@jarthur.cs.hmc.edu (Mark
Wilkins) writes:

<<What possible problems could be caused by having multiple calls to
WaitNextEvent in an application, especially if the purpose is to check for
interruption of a time-consuming process? ... In other words, why should I
care if I'm throwing away events which don't consist of a command period
or mouse click when those are the only two forms of interaction my
application will entertain when it's chugging away?  That is, assuming I'm
only throwing away events directed at my application...>>

It's mostly a matter of style, and of course it is generic Mac programming
advice to have only one place in your code call WNE. It sounds like you
know what you are doing, and perhaps this is the best way to handle it.
The complication of calling WNE from more than one place is that you have
to (or at least should) handle ALL events you get. In your case you are
going to ignore all events except the ones that can terminate your loop.
It's most important that you call WNE periodically (and often), for the
reasons mentioned in my previous post, even if you don't handle all of the
events.

Besides the key and mouse events, there are other events you may get. You
can't really get switched out if you ignore mouse clicks outside of your
window, but another process could do something that causes an update event
in one of your windows. Or a high-level event could get passed to you (if
your program accepts them). If you call WNE but can't respond to these
events in your computation loop, your window won't be updated and you
won't be able to process Apple Events. In your case maybe this is not a
big deal.

There is no "hard" reason to have only one WNE call in your program, as
long as you know that you may lose events.

Gregory Jorgensen
Radix Consulting Inc.

+++++++++++++++++++++++++++

>From kluev@jonathan.srcc.msu.su (Kluev)
Date: Sun, 28 Aug 94 18:13:09 +0400
Organization: (none)

In article <33h95e$ekn@search01.news.aol.com>
radixinc@aol.com (RadixInc) wrote:

> In article <Cv2Izo.Ao1@odin.corp.sgi.com>, rhn@waltz.engr.sgi.com
(Ron
> Nicholson) writes:
> <<
> First I install a VBL task whose only function is to increment a
global
> variable.  That gives me a tickcount variable that can be read
without
> a function call.  You can also use the TickCount() access function.
> (Or you can just use the lowmem global Ticks at $016A if you aren't
> strictly following Apple's guidelines.  Would I do that? :-)
> >>
> This is silly. Just call TickCount(), or if you have to, just look at
> Ticks. You are overly worried about performance, yet you install a
VBL
> task that does the same thing as an existing VBL task (how do you
think
> Ticks gets updated in the first place?).

First: There is no special VBL task that increments Ticks.
Second: Installing VBLTask that increments global variable gives you
much less accuracy than looking into Ticks (TickCount). This inaccuracy
will heavily depend on machine load and may rise up to several "real"
ticks against one "your" tick. Ticks is guaranteed to be incremented
every tick, but your VBLTask (which contains 1 in vblCount) is not
guaranteed to be called every tick.

> WaitNextEvent from more than one place in your program). And rather
than
> using Ticks and the local counter, use a modulo calculation on your
loop
> variable; e.g. check for an event every 10,000 iterations or so.

This is bad practice. If "10,000" is hard-coded you will get different
response time on different machines. It may be computed at start-time.
But think: machine load (VBLs for example) may vary during program
execution. Processor cache may be turned on/off. All this and more
will invalidate this "10,000" estimate. Ticks is better.

Michael Kluev.

+++++++++++++++++++++++++++

>From radixinc@aol.com (RadixInc)
Date: 29 Aug 1994 02:13:04 -0400
Organization: America Online, Inc. (1-800-827-6364)

In article <584486046668@jonathan.srcc.msu.su>, kluev@jonathan.srcc.msu.su
(Kluev) writes:

<<First: There is no special VBL task that increments Ticks.>>

Not on newer Macs, no. Ticks used to get updated by a VBL task, but now it
is synthesized. It doesn't matter how it gets updated; the point is that
it is better to get the value of Ticks, either by function call or reading
the global directly. If you use the Universal Headers you can read the
Ticks global and stay compatible by using LMGetTicks(). For historical
reasons it's easier to pretend that Ticks is incremented at VBL time, even
though on most Macs it isn't actually done that way. I apologize if anyone
was confused or misled by my statement, but it really makes no difference
how Ticks gets incremented, and by design it appears that it is done at
VBL time.

<<This is bad practice. If "10,000" is hard-coded you will get different
response time on different machines.>>

Obviously, but you are misreading my message. I wasn't suggesting
hard-coding the number 10,000, or any other number--I was suggesting a
modulo calculation based on SOME modulus. The actual number used could be
any value, and could be calculated in advance to account for differences
among machines. 10,000 was simply an illustrative example, and that's why
I wrote "e.g. check for an event every 10,000 iterations or so."  "e.g."
is an abbrevation for "exempli gratia," meaning "for example," not to be
confused with "i.e.," (id est), meaning "that is." This should be
self-evident to anyone capable of writing a VBL task in the first place,
and therefore I didn't see any reason to exhaustively explain what I was
suggesting. Quod erat demonstrandum.

<<But think: machine load (VBLs for example) may vary during program
execution. Processor cache may be turned on/off. All this and more
will invalidate this "10,000" estimate. Ticks is better.>>

I agree, but the original post, and my response, were discussing other
approaches. My suggestion, which was followed up by email, was to simply
read the value of Ticks and be done with it. Done correctly the modulus
method is a legitimate way to handle the problem, if for some reason the
programmer doesn't want to use Ticks.

Gregory Jorgensen
Radix Consulting Inc.

+++++++++++++++++++++++++++

>From besbris@jeeves.ucsd.edu (David Besbris)
Date: 29 Aug 1994 10:25:39 GMT
Organization: The Avant-Garde of the Now, Ltd.

Kluev (kluev@jonathan.srcc.msu.su) wrote:
(snip)

: First: There is no special VBL task that increments Ticks.
: Second: Installing VBLTask that increments global variable gives you
: much less accuracy than looking into Ticks (TickCount). This inaccuracy
: will heavily depend on machine load and may rise up to several "real"
: ticks against one "your" tick. Ticks is guaranteed to be incremented
: every tick, but your VBLTask (which contains 1 in vblCount) is not
: guaranteed to be called every tick.

(snip)

: This is bad practice. If "10,000" is hard-coded you will get different
: response time on different machines. It may be computed at start-time.
: But think: machine load (VBLs for example) may vary during program
: execution. Processor cache may be turned on/off. All this and more
: will invalidate this "10,000" estimate. Ticks is better.

: Michael Kluev.

Ticks is INDEED incremented by a system-installed VBL task, and is NOT
guaranteed to be inceremented exactly  once evey tick. (for the reasons that
you mention about the inaccuracy of using a VBL task.) I'm curious, why do you
say otherwise? 


-Dave 

One of the last Mac Pascal programmers...

besbris@jeeves.ucsd.edu


+++++++++++++++++++++++++++

>From kluev@jonathan.srcc.msu.su (Kluev)
Date: Tue, 30 Aug 94 16:42:18 +0400
Organization: (none)

In article <33sd33$4lh@network.ucsd.edu>
besbris@jeeves.ucsd.edu (David Besbris) wrote:

> Kluev (kluev@jonathan.srcc.msu.su) wrote:
> (snip)
> 
> : First: There is no special VBL task that increments Ticks.
> : Second: Installing VBLTask that increments global variable gives
you
> : much less accuracy than looking into Ticks (TickCount). This
inaccuracy
> : will heavily depend on machine load and may rise up to several
"real"
> : ticks against one "your" tick. Ticks is guaranteed to be
incremented
> : every tick, but your VBLTask (which contains 1 in vblCount) is not
> : guaranteed to be called every tick.
> 
> : Michael Kluev.
> 
> Ticks is INDEED incremented by a system-installed VBL task, and is
NOT
> guaranteed to be inceremented exactly  once evey tick. (for the
reasons that
> you mention about the inaccuracy of using a VBL task.) I'm curious,
why do
> you say otherwise? 
> 
> -Dave 

Here's the story on how VBL mechanism work, at least as I understand
it. Ticks is updated by "VBL mechanism", *not* by system-installed
VBL task. The first thing that is done by VBL mechanism is incrementing
Ticks variable. Then it gets sure that it is not already running
(by looking in VBLQueue). If it is already running, there is nothing
to do, just return. If it is not running, mechanism decrements
vblCounts of VBL tasks, and calls those, which have zero in vblCount.
While VBL task is getting called, VBL mechanism may be entered again.
(This is another story, how is it getting called: is it real video card
interrupt, or is it triggered VIA interrupt. For now it is important
only, that mechanism is getting called every 1/60 sec or so.) In this
case the only thing it does is incrementing Ticks variable. So Ticks
*is guaranteed* (if we aren't talking about situations when interrupts
are disabled for a long time, e. g. diskette formatting) to be
incremented every tick, but VBL task that has 1 in vblCount
*is not guaranteed* to be called every tick. As far as I know all
Macs since 1984 share this scheme.

If you don't believe me, disassemble a few bytes of ROM above the
code that calls your VBL task (on my machine it starts at
"_VRemove+16".
You will see:

+0014 RTS
; Starting point of "VBL mechanics"
+0016 ADDQ.L #$1, Ticks;     increments Ticks global
+001A .....
+0020 BSET #$06, VBLQueue;   test if it is already running
+0026 BNE _VRemove+0014;     nothing can do - return.

If you still don't believe me, write a small test. Install VBL task
that does the following:
  ...
  Task-> vblCount = 1;            // reinstalls itself
  MyTicks++;                      // increments global
  Delay(10, &L);                  // degrades machine performance,
                                  // (emulates Mac Plus or so)
// You may try to use this "for" loop instead of Delay
//  for (i = 0; i < 1000000L; i++);
  ...

In your main write:
   ...
   VInstall(...);            // installs VBL task with 1 in vblCount
   MyOldTicks = MyTicks;     // saves old timers
   OldTicks = TickCount();
   Delay(60*10);             // waits 10 seconds
   MyNewTicks = MyTicks;
   NewTicks = TickCount();   // gets new timers

   NumToString(MyNewTicks - MyOldTicks, String);
   DebugStr(String);
   NumToString(NewTicks - OldTicks, String);
   DebugStr(String);              // makes things obvious

...You will notice a big difference.

As someone else pointed, for more exact and/or long-term measurements
it is better to use other mechanisms instead of Ticks (e. g. Time
Manager or GetDateTime).

Michael Kluev.

+++++++++++++++++++++++++++

>From kluev@jonathan.srcc.msu.su (Kluev)
Date: Fri, 2 Sep 94 21:33:30 +0400
Organization: (none)

In article <33ire6$s4i@search01.news.aol.com>
radixinc@aol.com (RadixInc) wrote:

> I understand that the overhead of making the WNE toolbox call and
polling
> for events is time consuming, especially if you are trying to squeeze
the
> most performance out of a loop. Lots of programs just put up the
"watch"
> cursor and ignore all events while they do their computation. This is
> considered bad etiquette, because WNE does more than just feed events
to
> your app. It is the only way to let other processes have time.

EventAvail and GetNextEvent also allow other processes to work. Their
"time consuming" is approximately the same as of WaitNextEvent.

> Also keep in mind that, depending on the speed of the Mac you are
running
> on, events don't live all that long. The event queue only holds 20
events,
> and if you aren't removing them with WNE the old events will be lost.
That
> means you have to poll for events fast enough to catch them before
they
> are lost. User-interface events will happen much less frequently than
> every 10 ticks, but network events may happen very fast on certain
Macs.

Do you use those cool "network" events? This is not recommended
practice.

Michael Kluev.

+++++++++++++++++++++++++++

>From radixinc@aol.com (RadixInc)
Date: 25 Aug 1994 01:11:10 -0400
Organization: America Online, Inc. (1-800-827-6364)

In article <Cv2Izo.Ao1@odin.corp.sgi.com>, rhn@waltz.engr.sgi.com (Ron
Nicholson) writes:

<<
A program has to call WaitNextEvent to cleanly check for a keyboard
abort (command-period).  I tried this in an inner loop of a compute
intensive application and it slowed down the computation noticeably.
I had to figure out a way to poll often enough to not make the user
interface seem sluggish, while slowing calculation down minimally.
>>

A program has to call WaitNextEvent to cleanly do a lot of things. If you
aren't checking events you are hogging the machine and not letting other
apps have time. And what do you mean "not make the user interface seem
sluggish?" What user interface do you have when you aren't checking for
events?

<<
First I install a VBL task whose only function is to increment a global
variable.  That gives me a tickcount variable that can be read without
a function call.  You can also use the TickCount() access function.
(Or you can just use the lowmem global Ticks at $016A if you aren't
strictly following Apple's guidelines.  Would I do that? :-)
>>

This is silly. Just call TickCount(), or if you have to, just look at
Ticks. You are overly worried about performance, yet you install a VBL
task that does the same thing as an existing VBL task (how do you think
Ticks gets updated in the first place?). You can use any DOCUMENTED
low-memory globals, like Ticks, without getting in trouble. Certainly
given the choice between that and installing a VBL, DTS would advise the
former.

As for the code sample, why not call EventAvail periodically with an event
mask that ignores events you don't care about? That way you won't end up
with an event loop inside your compute-intensive loop and (presumably)
another one in your main program. (DTS will certainly frown on calling
WaitNextEvent from more than one place in your program). And rather than
using Ticks and the local counter, use a modulo calculation on your loop
variable; e.g. check for an event every 10,000 iterations or so.

Make it work first, optimize the slow parts later [after identifying the
slow parts].

Gregory Jorgensen
Radix Consulting Inc.

---------------------------

>From dlopez@sailsun (Dean Lopez)
Subject: Standard C Libraries: use them?
Date: 12 Aug 1994 18:46:29 GMT
Organization: NASA Johnson Space Center, Houston, TX, USA

I am wondering about the 'legitimacy' of using the Standard C Libraries
in my Mac applications.  As a C programmer on other systems, I've become
quite fond of the Standard C libraries - stdio.h in particular.  The
problem with using them on the Mac, as I'm sure you all know, is the way
files are reference via FILE* 'ers compared with the File Manager's 
file reference numbers.  If I use the File Manager, I don't see how I
can use the stdio.h functions which require a FILE*.  And if I use the
stdio.h functions, I can't use some of the File Manager's goodies.

Has anybody figured out how to convert the FILE structure info into the
FSSpec structure? (I mean written the routines already, I really don't
have the time right now to attempt it myself).
I'd just like to be able to interchange how I reference a file right
now, in the same way on say, a Data General system using AOS will let
me reference a file either with the stdio or Unix calls.

Is there a reason NOT to try to use either/or?

Any and all advice welcome. NOTE: if you e-mail me, see my email addresses
below, don't use what's in my reply-to field.  Its messed up somehow.
--
+---------------------------------------+-----------------------------+
| Dean Lopez                            |                             |
| SAIL DPS Engineer                     | dlopez@sailsun.jsc.nasa.gov |
| Rockwell Space Operations Co.         | deanlopez@aol.com           |
| JSC Shuttle Avionics Integration Lab  | dean_lopez@maclair.cld9.com |
+---------------------------------------+-----------------------------+
#include <standard_disclaimer.h>
/* The opinions expressed are all mine.
   RSOC doesn't speak for me and I don't speak for RSOC
   After all, I'm only an engineer - what do I know?     */

+++++++++++++++++++++++++++

>From rollin@newton.apple.com (Keith Rollin)
Date: Thu, 18 Aug 1994 04:26:36 -0800
Organization: Apple ][ -> Mac -> Taligent -> Newton -> Windows?

In article <32gg25$of9@pendragon.jsc.nasa.gov>, dlopez@sailsun (Dean
Lopez) wrote:

>I am wondering about the 'legitimacy' of using the Standard C Libraries
>in my Mac applications.  As a C programmer on other systems, I've become
>quite fond of the Standard C libraries - stdio.h in particular.  The
>problem with using them on the Mac, as I'm sure you all know, is the way
>files are reference via FILE* 'ers compared with the File Manager's 
>file reference numbers.  If I use the File Manager, I don't see how I
>can use the stdio.h functions which require a FILE*.  And if I use the
>stdio.h functions, I can't use some of the File Manager's goodies.
>
>Has anybody figured out how to convert the FILE structure info into the
>FSSpec structure? (I mean written the routines already, I really don't
>have the time right now to attempt it myself).
>I'd just like to be able to interchange how I reference a file right
>now, in the same way on say, a Data General system using AOS will let
>me reference a file either with the stdio or Unix calls.
>
>Is there a reason NOT to try to use either/or?

Check the Mac Technotes:

"Frequently, developers want to use both Macintosh file I/O and C file
I/O.  Developers who do this must keep in mind that they are combining two
distinct file representations (the Macintosh and ANSI C).  The only
limitation on mixing HFS and C I/O functions is that they cannot be mixed
on the same open file.  There are three reasons why this cannot be done.

"First, there is no routine that maps between a C FILE struct (returned by
fopen()) to an HFS fRefNum (needed to call HFS functions).  Similarly,
there is no call to create a FILE struct given an fRefNum returned by
FSOpen().  Thus, there is no way that the information from an fopen() call
could be used to do a FSRead().

"Second, even if the first problem were solved, the C libraries eventually
call the HFS file system, but keep some internal state information.  So,
if you call HFS directly (say, SetFPos()), the C file system has no way of
knowing a call was made and, therefore, doesn¹t update its state
information. 

"Similarly, there is no mechanism for synchronizing the C library¹s
buffers.  For example, you perform an fwrite() with some number of
characters which get put into a buffer without flushing it.  Then you
perform an FSWrite() with something else.  Neither the C library nor HFS
are aware that the other has written to the file.

"Simply put, you cannot make HFS calls on a file opened with fopen() or
fdopen(); you cannot use C library I/O on a file opened under HFS."

- --------------------------------------------------------------------------
Keith Rollin --- Phantom Programmer --- Apple Computer, Inc. --- Team Newton

+++++++++++++++++++++++++++

>From cjsmith@nwu.edu (Jeremy Smith)
Date: 18 Aug 1994 15:37:49 GMT
Organization: Northwestern University, Evanston, IL  USA

   I'm not sure, what exactly you're trying to do, but if you have a copy
of Think Reference, go to misc. topics/Code Example Orphans/Printing a
Text File and look at the GotATextFile procedure.  This uses a medly of
toolbox and ANSI file routines.  Good luck,

   Jeremy Smith   
   cjsmith@nwu.edu

+++++++++++++++++++++++++++

>From phils@bedford.symantec.com (Phil Shapiro)
Date: Mon, 22 Aug 1994 14:37:27 -0400
Organization: Symantec Corp.

In article <rollin-1808940426360001@mac691.kip.apple.com>,
rollin@newton.apple.com (Keith Rollin) wrote:

| In article <32gg25$of9@pendragon.jsc.nasa.gov>, dlopez@sailsun (Dean
| Lopez) wrote:
| 
| >I am wondering about the 'legitimacy' of using the Standard C Libraries
| >in my Mac applications.  As a C programmer on other systems, I've become
| >quite fond of the Standard C libraries - stdio.h in particular.  The
| >problem with using them on the Mac, as I'm sure you all know, is the way
| >files are reference via FILE* 'ers compared with the File Manager's 
| >file reference numbers.  If I use the File Manager, I don't see how I
| >can use the stdio.h functions which require a FILE*.  And if I use the
| >stdio.h functions, I can't use some of the File Manager's goodies.
| >
| >Is there a reason NOT to try to use either/or?
| 
| Check the Mac Technotes:
| 
| "First, there is no routine that maps between a C FILE struct (returned by
| fopen()) to an HFS fRefNum (needed to call HFS functions).  Similarly,
| there is no call to create a FILE struct given an fRefNum returned by
| FSOpen().  Thus, there is no way that the information from an fopen() call
| could be used to do a FSRead().

The Mac Technotes have always assumed that everyone is using the MPW
development system. If you're using THINK, you *can* get the refnum for an
open FILE. It's stored in the field called "refnum". You could also write
a stdio routine that builds a FILE* from an open file, since the THINK
libraries ship with full source. But that's a fair amount of work just
because you happen to like ANSI I/O. You will only be able to use the code
in THINK, too.

Unless you're porting a lot of code that already uses ANSI I/O, you're
much better off going with straight Mac I/O.

   -phil

+++++++++++++++++++++++++++

>From nagle@netcom.com (John Nagle)
Date: Tue, 23 Aug 1994 02:02:25 GMT
Organization: NETCOM On-line Communication Services (408 261-4700 guest)

phils@bedford.symantec.com (Phil Shapiro) writes:
>In article <rollin-1808940426360001@mac691.kip.apple.com>,
>rollin@newton.apple.com (Keith Rollin) wrote:
>| In article <32gg25$of9@pendragon.jsc.nasa.gov>, dlopez@sailsun (Dean
>| Lopez) wrote:
>| >I am wondering about the 'legitimacy' of using the Standard C Libraries
>| >in my Mac applications.  As a C programmer on other systems, I've become
>| >quite fond of the Standard C libraries - stdio.h in particular.  

>The Mac Technotes have always assumed that everyone is using the MPW
>development system. If you're using THINK, you *can* get the refnum for an
>open FILE.

>Unless you're porting a lot of code that already uses ANSI I/O, you're
>much better off going with straight Mac I/O.

        Of course, then you have to try to read a text file with the
Toolbox calls, a difficult, slow, and badly documented operation.
Anybody have the obscure tech note reference on doing that?

					John Nagle

+++++++++++++++++++++++++++

>From zstern@adobe.com (Zalman Stern)
Date: Tue, 23 Aug 1994 05:51:49 GMT
Organization: Adobe Systems Incorporated

That the Mac API prevents the use of stdio in many cases is just a bug. Any  
reasonable UNIX system provides functions to map a FILE * to a file  
descriptor (the moral equivalent of a Mac file reference number) and to open  
a FILE * from a file descriptor. (They're called fileno and fdopen  
respectively.) The conventions for switching between system call level I/O  
and stdio are a bit arcane but workable for most uses of this functionality.  
(The fdopen call is necessary because UNIX has a unified model of stream I/O  
which a large number of things obey. There are many ways to get a file  
descriptor, but once you have one it behaves according to this model and  
turning it into a stdio stream is very useful.)

I've seen a number of posts recently that express the attitude that there is  
no point in using portable API's for Macintosh programming because Mac  
applications are inherently non-portable. (Or perhaps these posters feel a  
program isn't a good Macintosh application unless its non-portable.) People  
who feel this way are quickly becoming economic roadkill, and deservedly so.  
One writes non-portable code because less than ideal circumstances forces  
one to, not because it is desirable.
--
Zalman Stern		   zalman@adobe.com		    (415) 962 3824
Adobe Systems, 1585 Charleston Rd., POB 7900, Mountain View, CA 94039-7900
 Please do not change color while I am talking to you -- MC 900 Ft Jesus.

+++++++++++++++++++++++++++

>From tree@bedford.symantec.com (Tom Emerson)
Date: Tue, 23 Aug 1994 06:33:54 -0500
Organization: Symantec Development Tools Group

> >Unless you're porting a lot of code that already uses ANSI I/O, you're
> >much better off going with straight Mac I/O.
> 
>         Of course, then you have to try to read a text file with the
> Toolbox calls, a difficult, slow, and badly documented operation.
> Anybody have the obscure tech note reference on doing that?

IM: Files, p. 2-90 & 2-122.

   -tre

-- 
Tom Emerson                                              Software Engineer
Development Tools Group                               Symantec Corporation
                          tree@bedford.symantec.com
  "I dreamed I had to take a test, in a Dairy Queen, on another planet."

+++++++++++++++++++++++++++

>From quinn@cs.uwa.edu.au (Quinn "The Eskimo!")
Date: Thu, 25 Aug 1994 11:40:13 +0800
Organization: Department of Computer Science, The University of Western Australia

In article <1994Aug23.055149.5764@adobe.com>, zstern@adobe.com (Zalman
Stern) wrote:

>That the Mac API prevents the use of stdio in many cases is just a bug.

I disagree with this.  Any API that promotes the use of full paths to
denote files is fundamentally broken for use on a Mac, mainly because
multiple volumes can have the same name.  Of course you can work around
this problem but there comes a point where you've got to decide whether
your workaround is worth the effort.
-- 
Quinn "The Eskimo!"        "Scout in a can. Simple, cheap, easy
                            to use and it's expendable!"

+++++++++++++++++++++++++++

>From zstern@adobe.com (Zalman Stern)
Date: Thu, 25 Aug 1994 07:10:14 GMT
Organization: Adobe Systems Incorporated

Quinn "The Eskimo!" writes
> In article <1994Aug23.055149.5764@adobe.com>, zstern@adobe.com (Zalman
> Stern) wrote:
> >That the Mac API prevents the use of stdio in many cases is just a bug.
> 
> I disagree with this.  Any API that promotes the use of full paths to
> denote files is fundamentally broken for use on a Mac, mainly because
> multiple volumes can have the same name.  Of course you can work around
> this problem but there comes a point where you've got to decide whether
> your workaround is worth the effort.

Fine write a function like so:

	FILE * FSfopen(FSSpec *fileSpec, char *mode);

or perhaps a function that pops up a standard file dialog and opens a file  
that way. Then you can write the file processing routines in a portable  
fashion. The other alternative is to write your own stream library and  
ensure that it is portable, but that is fraught with problems. (E.g. the  
MacApp stream implementation which does no buffering.) I prefer not to  
re-invent the wheel unless I have to.

My original point is that with a little work in the stdio implementation one  
can go back and forth easily. My use of "The Mac API" is wrong. I meant the  
standard C library implementation combined with the toolbox requirements.  
Obviously the C library implementation is a better choice to change.
--
Zalman Stern		   zalman@adobe.com		    (415) 962 3824
Adobe Systems, 1585 Charleston Rd., POB 7900, Mountain View, CA 94039-7900
 Please do not change color while I am talking to you -- MC 900 Ft Jesus.

---------------------------

>From redial <redial@netcom.com>
Subject: Summary of 'Safe Save' problem - IM:Files flawed!
Date: Thu, 25 Aug 1994 04:29:12 GMT
Organization: NETCOM On-line Communication Services (408 261-4700 guest)

Netters -

Awhile ago I posted a request for help with a problem I was having
implementing the 'Safe Save' routine outlined in Inside Macintosh:Files, pp.
1-25,26.  A 'safe save' is a save routine which creates a temporary file on
disk, saves the data to it, and - if no error occurs - swaps the the
directory information for the two files, and then deletes the temporary file.
 The advantage over a 'direct save' to the existing file is that if an error
were to occur, the existing file could be damaged and its data erased or
corrupted.  The IM example code is in Pascal (naturally), but since I am
working in C I attempted to translate it to that language.  The problem I ran
into was that after the directory swap between the files, I would get a 'file
busy' error when I attempted to delete the temporary file.  This was quite
puzzling since the code clearly executes a command to close the temporary
file immediately before the delete command.

Scott Bronson pointed out that the swap command, FSpExchangeFiles, swaps
the FCBs too, and recommended closing both files before swapping.  However, a
comment line in the original pascal example directed that the data fork of
the existing file be opened and left open!  I wondered why, but Scott thought
this was just another example of how inaccurate the code examples in IM can
be.  The bugginess of the 'Safe Save' routine certainly attests to this fact!

Further snooping led to several bits of info about the two files which
enabled Troy Gaul to correctly diagnose that the IM example code called for a
resource to be written to the original file BEFORE the swap.  Thus, it
contained the resource and the old data, while the temporary file contained
only the new data.  AFTER the swap, the original file then contained only the
new data while the temporary file contained the resource and the old data. 
Troy also pointed out that since FSpExchangeFiles also swaps the FCBs if
either or both files are open, the FSClose routine needs to use the path
reference number of the _original_ file in order to actually close the
temporary file!  This means that future references to the original file will
require the use of the temporary file's path refnum, so it must be saved.

Yet another error was discovered by Jens-Uwe Mager.  The IM:Files example
used the FSClose routine to close the resource fork of the original file, but
this did not cause the resource data to actually be flushed to the disk.  He
correctly suggested the use of CloseResFile, which (contrary to my initial
response to him) does work exactly like it should.

The first part of the fix is to move the resource creating code from the
DoSaveAsCmd routine to the DoWriteFile routine.  However, you must continue
to allow the DoSaveAsCmd routine to open the original file's data fork and
leave it open.  This is important because of the interplay between the 'Save'
and the 'Save As...' file menu commands.  The first time the user saves his
file, the DoSaveAsCmd routine is going to be executed regardless of which
command was chosen.  Thereafter, each time the user selects the 'Save'
command, the DoSaveAsCmd routine is bypassed and flow goes directly to
DoWriteData.  You could allow DoWriteData to open the original file's data
fork, but then you'd also have to close it again before leaving the routine. 
Putting just one call to open the data fork in the DoSaveAsCmd is more
efficient.

The second part of the fix is to make the DoWriteFile routine create the
temporary file, copy the resource to its resource fork, and close the
resource fork with CloseResFile.  Then the routine should open the temp
file's data fork, write the current data to it, and leave it open also.  Do
the swap using FSpExchangeFiles. NOW the path reference numbers of the two
files, which locate their data in memory, are reversed, but their FSSpecs are
not.  Close the temp file by calling FSClose with the _original_ file's path
reference number.  Save the _temporary_ file's path reference number for
future use with the file, and then delete the temp file by calling FSpDelete
with the temporary file's FSSpec.

Sorry to be so long winded.  If anyone wishes to see the final code, drop me
an email.  And sincere thanks to all who helped.

 ===============================================================
|  Ron Goebel                  |                                |
|  G & V Systems               | Whatdya mean 'I don't get it?' |
|  Internet: redial@netcom.com |                                |
 ===============================================================

---------------------------

>From redcon@xmission.com (Dan Eldridge)
Subject: What Happens in the Resource Fork
Date: 18 Aug 1994 14:23:26 GMT
Organization: Redcon

Hi

Here's A general question, that I'm sure someone can answer,
What happens in the Resource Fork if a program significantly and often
changes the size of one of the resources, does the fork get fragmented, or
does the whole file get rewritten so that the forks are all contiguous?



Just Wondering

-- 
  Dan
Redcon

***
insert favorite corn dog joke here
***

+++++++++++++++++++++++++++

>From mclow@san_marcos.csusm.edu (Marshall Clow)
Date: Thu, 18 Aug 1994 09:26:20 -0800
Organization: Aladdin Systems

In article <redcon-1808940824560001@slc17.xmission.com>,
redcon@xmission.com (Dan Eldridge) wrote:

> Hi
> 
> Here's A general question, that I'm sure someone can answer,
> What happens in the Resource Fork if a program significantly and often
> changes the size of one of the resources, does the fork get fragmented, or
> does the whole file get rewritten so that the forks are all contiguous?
> 
   My experience has been that if you make resources smaller (or possibly
delete them), the extra space in the file is left unused, but if you add a
resource or make one larger, then it is added at the end and the file is
compacted in UpdateResFile. (which is called from CloseResFile)

-- Marshall

-- 
Marshall Clow
Aladdin Systems
mclow@san_marcos.csusm.edu

+++++++++++++++++++++++++++

>From Jens Alfke <jens_alfke@powertalk.apple.com>
Date: Wed, 24 Aug 1994 17:53:54 GMT
Organization: Apple Computer

Dan Eldridge, redcon@xmission.com writes:
> What happens in the Resource Fork if a program significantly and often
> changes the size of one of the resources, does the fork get fragmented, or
> does the whole file get rewritten so that the forks are all contiguous?

When you call UpdateResFile or CloseResFile, all the data gets shuffled
around on disk until it's contiguous. Needless to say this can be very slow.
Remember those long delays you sometimes get when you close the Monitors
control panel or use some utility to update the desktop pattern? That's the
cause; the System file is rather large, esp. pre-7.1 systems that had all the
fonts in the System file itself. And the best part is, if you decide your
system's hung and reboot, you've just destroyed your system file! That's the
major reason we made Wallpaper not store its desktop pattern in the System
file.

All the more reason why (let's all chant it together) "The Resource Manager
is not a database!"

--Jens Alfke                           jens_alfke@powertalk.apple.com
                   "A man, a plan, a yam, a can of Spam ... Bananama!"

+++++++++++++++++++++++++++

>From kluev@jonathan.srcc.msu.su (Kluev)
Date: Thu, 25 Aug 94 20:58:39 +0400
Organization: (none)

In article <1994Aug24.175354.27836@gallant.apple.com>
Jens Alfke <jens_alfke@powertalk.apple.com> wrote:

> Dan Eldridge, redcon@xmission.com writes:
> > What happens in the Resource Fork if a program significantly and
often
> > changes the size of one of the resources, does the fork get
fragmented, or
> > does the whole file get rewritten so that the forks are all
contiguous?
> 
> When you call UpdateResFile or CloseResFile, all the data gets
shuffled
> around on disk until it's contiguous. Needless to say this can be
very slow.

This data compacting occurred in "logical" space of fork instead of
"physical". Compacting removes empty space in fork (not on disk)
created when a resource was removed, made smaller, or larger.
"Physically", file can be shuffled around all the disk.
So the answer is: Yes, the fork get fragmented.

Michael Kluev.

---------------------------

>From schwarz@kodak.com (Doug Schwarz)
Subject: Why does NewGWorld do this?
Date: Tue, 23 Aug 1994 20:07:42 GMT
Organization: Eastman Kodak Company, Rochester, NY

I am trying to create multiple offscreen graphics worlds.

    QDErr           err1, err2;
    PixMapHandle    pixBase1, pixBase2;
    GWorldPtr       theGWorld1, theGWorld2;
    CGrafPtr        currentPort;
    GDHandle        currentDevice;
    Rect            boundsRect;

    GetGWorld(&currentPort, &currentDevice);
    err1 = NewGWorld(&theGWorld1, 32, &boundsRect, NULL, NULL, 0);
    pixBase1 = GetGWorldPixMap(theGWorld1);
    SetGWorld(currentPort, currentDevice);

    GetGWorld(&currentPort, &currentDevice);
    err2 = NewGWorld(&theGWorld2, 32, &boundsRect, NULL, NULL, 0);
    pixBase2 = GetGWorldPixMap(theGWorld2);
    SetGWorld(currentPort, currentDevice);


In the code fragment above, theGWorld1 gets allocated just fine (and pixBase1
looks ok), but theGWorld2 is NULL (and pixBase2 is not valid).  Both err1
and err2 are zero.  What is going on/what am I doing wrong?  There is no
mention in IM VI what a zero GWorldPtr means.  I had assumed that it would
mean that there wasn't enough memory to allocate the pixel maps, but the pixel
maps aren't very large and I have the memory partition for the app set plenty
large.  Thanks for any help you can give me.

Doug Schwarz
Eastman Kodak Company
schwarz@kodak.com

+++++++++++++++++++++++++++

>From python@world.std.com (Steven J. Bushell)
Date: Wed, 24 Aug 1994 11:48:59 -0500
Organization: Kodak Electronic Printing Systems, Inc.

In article <schwarz-2308941607420001@150.220.61.78>, schwarz@kodak.com
(Doug Schwarz) wrote:
[ code deleted ]
> In the code fragment above, theGWorld1 gets allocated just fine (and pixBase1
> looks ok), but theGWorld2 is NULL (and pixBase2 is not valid).  Both err1
> and err2 are zero.  What is going on/what am I doing wrong?  There is no
> mention in IM VI what a zero GWorldPtr means.  I had assumed that it would
> mean that there wasn't enough memory to allocate the pixel maps, but the pixel
> maps aren't very large and I have the memory partition for the app set plenty
> large.  Thanks for any help you can give me.
> 
> Doug Schwarz
> Eastman Kodak Company
> schwarz@kodak.com

It's an undocumented feature of NewGWorld that it returns no error when it
has insufficient memory to allocate the GWorld.  You should ALWAYS check
the GWorldPtr to determine if the call was successful.  The only time you
get errors back from NewGWorld is when you pass ridiculous parameters to
it.  I've never seen any other errors come back from it.

Considering this, plus the fact that the first call to NewGWorld was
successful, you can pretty safely assume that you are short on memory. 
Double-check your boundsRect, and make sure your heap isn't fragmented
too.  A quick way to confirm that it is a memory problem would be to cut
the boundsRect in half and see if both calls succeed.  If they don't,
check to make sure your heap's okay.

- Steve

//////////
//
//   Steve Bushell
//   python@world.std.com
//
//   "It's always the quiet ones."
//
//////////

+++++++++++++++++++++++++++

>From dab@zork.tiac.net (Dana Basken)
Date: 24 Aug 1994 16:41:23 GMT
Organization: Rockland Software

In article <python-2408941148590001@155.50.26.175>
python@world.std.com (Steven J. Bushell) writes:

> It's an undocumented feature of NewGWorld that it returns no error when it
> has insufficient memory to allocate the GWorld.  You should ALWAYS check
> the GWorldPtr to determine if the call was successful.  The only time you
> get errors back from NewGWorld is when you pass ridiculous parameters to
> it.  I've never seen any other errors come back from it.

It's odd that you have never seen any other errors return from
NewGWorld.  If and when I try to create a GWorld using NewGWorld that
is too large to fit into memory, I get a result code of -108
(memFullErr) every time.  In my experience, I've never seen NewGWorld
not create a GWorld and pass back noErr.

I would look for some other reason in the failure of the allocation of
your GWorld.

- Dana

- -
Dana Basken              dab@mote.tiac.net
Rockland Software

+++++++++++++++++++++++++++

>From tg3@u.washington.edu (Thurman Gillespy III)
Date: Wed, 24 Aug 1994 11:55:51 -0800
Organization: Dept of Radiology, Univ of Washington

In article <schwarz-2308941607420001@150.220.61.78>, schwarz@kodak.com
(Doug Schwarz) wrote:

> I am trying to create multiple offscreen graphics worlds.
> 
>     QDErr           err1, err2;
>     PixMapHandle    pixBase1, pixBase2;
>     GWorldPtr       theGWorld1, theGWorld2;
>     CGrafPtr        currentPort;
>     GDHandle        currentDevice;
>     Rect            boundsRect;
> 
>     GetGWorld(&currentPort, &currentDevice);
>     err1 = NewGWorld(&theGWorld1, 32, &boundsRect, NULL, NULL, 0);
>     pixBase1 = GetGWorldPixMap(theGWorld1);
>     SetGWorld(currentPort, currentDevice);
> 
>     GetGWorld(&currentPort, &currentDevice);
>     err2 = NewGWorld(&theGWorld2, 32, &boundsRect, NULL, NULL, 0);
>     pixBase2 = GetGWorldPixMap(theGWorld2);
>     SetGWorld(currentPort, currentDevice);
>
Err, you HAVE defined boundsRect further, havn't you?
-- 
Thurman Gillespy III             |  tg3@u.washington.edu
Department of Radiology, SB-05   |  voice (206)543-3320
University of Washington         |  fax   (206)543-6317
Seattle, WA 98195                |

+++++++++++++++++++++++++++

>From snozer@cats.ucsc.edu (Daniel Craig Jalkut)
Date: 24 Aug 1994 21:21:31 GMT
Organization: University of California, Santa Cruz


In <schwarz-2308941607420001@150.220.61.78> schwarz@kodak.com (Doug Schwarz) writes:

>I am trying to create multiple offscreen graphics worlds.

>    QDErr           err1, err2;
>    PixMapHandle    pixBase1, pixBase2;
>    GWorldPtr       theGWorld1, theGWorld2;
>    CGrafPtr        currentPort;
>    GDHandle        currentDevice;
>    Rect            boundsRect;

>    GetGWorld(&currentPort, &currentDevice);
>    err1 = NewGWorld(&theGWorld1, 32, &boundsRect, NULL, NULL, 0);
>    pixBase1 = GetGWorldPixMap(theGWorld1);
>    SetGWorld(currentPort, currentDevice);

>    GetGWorld(&currentPort, &currentDevice);
>    err2 = NewGWorld(&theGWorld2, 32, &boundsRect, NULL, NULL, 0);
>    pixBase2 = GetGWorldPixMap(theGWorld2);
>    SetGWorld(currentPort, currentDevice);


>In the code fragment above, theGWorld1 gets allocated just fine (and pixBase1
>looks ok), but theGWorld2 is NULL (and pixBase2 is not valid).  Both err1
>and err2 are zero.  What is going on/what am I doing wrong?  There is no
>mention in IM VI what a zero GWorldPtr means.  I had assumed that it would
>mean that there wasn't enough memory to allocate the pixel maps, but the pixel
>maps aren't very large and I have the memory partition for the app set plenty
>large.  Thanks for any help you can give me.

>Doug Schwarz
>Eastman Kodak Company
>schwarz@kodak.com

Any GWorld references I've read have always insisted that you check
both the return value being noErr, *and* the GworldPtr being != NULL.  
Probably you are somehow passing NewGWorld parameters that seem ok, 
and it does it's job ok, but doesn't put the results where you expect
it to. I can't see from your example code anything that looks wrong in
the NewGWorld calls.  It is weird that you call GetGWorld and SetGWorld
before and after your NewGWorld calls, though.  I may be wrong, but  I 
don't think NewGWorld does any modification to the active GrafPort or
GDevice.  You only need to Get/SaveGworld before and after you do 
any drawing to the GWorld(just like a GrafPort, in fact I've seen it 
recommended that if you use GWorlds at all your just use Get/SaveGWorld
in *lieu* of Get/SavePort.

The main problem I ran into when learning GWorlds was running out of memory,
and it did return the proper error code.  I concur with the other person
who said that they have never had NewGWorld return noErr in  reaction 
to an out of memory error.  If you use GWorlds or anything else that is 
memory intensive, you will probably have to change the default heap size 
of your application from whatever compiler you use. 

-- 
 ____
/ /\ \	Daniel Craig Jalkut   	"All I know is that I don't know nothing,
-/--\-  snozer@cats.ucsc.edu	and that's FINE" -- Operation Ivy
X____X  UNIX, coffee, politics, punk-rock, Mac, women, food, and more. 


+++++++++++++++++++++++++++

>From Darrin Cardani <Darrin.Cardani@AtlantaGA.NCR.COM>
Date: Wed, 24 Aug 1994 19:34:38 GMT
Organization: AT&T Global Information Solutions, Atlanta

>In article <33ft7j$llk@sundog.tiac.net> Dana Basken writes: 
>In article <python-2408941148590001@155.50.26.175>
>python@world.std.com (Steven J. Bushell) writes:
>
>> It's an undocumented feature of NewGWorld that it returns no error when it
>> has insufficient memory to allocate the GWorld.  You should ALWAYS check
>> the GWorldPtr to determine if the call was successful.  The only time you
>> get errors back from NewGWorld is when you pass ridiculous parameters to
>> it.  I've never seen any other errors come back from it.
>
>It's odd that you have never seen any other errors return from
>NewGWorld.  If and when I try to create a GWorld using NewGWorld that
>is too large to fit into memory, I get a result code of -108
>(memFullErr) every time.  In my experience, I've never seen NewGWorld
>not create a GWorld and pass back noErr.

I too have seen the noErr, but no memory problem. Is there maybe more to
it than those 2 factors? (Maybe, there's enough mem., but it's too fragmented
or something wacko like that?)

Darrin







+++++++++++++++++++++++++++

>From schwarz@kodak.com (Doug Schwarz)
Date: Wed, 24 Aug 1994 20:26:47 GMT
Organization: Eastman Kodak Company, Rochester, NY

In article <33ft7j$llk@sundog.tiac.net>, dab@zork.tiac.net (Dana Basken) wrote:

> It's odd that you have never seen any other errors return from
> NewGWorld.  If and when I try to create a GWorld using NewGWorld that
> is too large to fit into memory, I get a result code of -108
> (memFullErr) every time.  In my experience, I've never seen NewGWorld
> not create a GWorld and pass back noErr.
> 
> I would look for some other reason in the failure of the allocation of
> your GWorld.
> 
> - Dana

I wrote a small application containing little more than my original code
fragment and I also get a result of -108 when there is not enough memory. 
It never returns a null GWorld and a zero error.  So, it seems that I need
to give a more complete description of my original problem.

I am using THINK C 7.0.3 and the TCL 1.1.3.  The allocation of the GWorlds
is done in the initialization method for a class.  I create two instances
of my class and initialize them like so:

    SetRect(&bounds, ...);
    instance1 = new(COffscreenPixMap);
    instance1->IOffscreenPixMap(bounds);
    instance2 = new(COffscreenPixMap);
    instance2->IOffscreenPixMap(bounds);

where, IOffscreenPixMap() is something like:


class COffscreenPixMap : CObject
{
private:
    CGrafPtr    currentPort;
    GDHandle    currentDevice;
    GWorldPtr   theGWorld;

public:
    void        IOffscreenPixMap(Rect);
};

void COffscreenPixMap::IOffscreenPixMap(Rect boundsRect)
{
    QDErr           err, qderr;
    PixMapHandle    pixBase;
    
    GetGWorld(&currentPort, &currentDevice);
    err = NewGWorld(&theGWorld, 32, &boundsRect, NULL, NULL, 0);
    qderr = QDError();
    pixBase = GetGWorldPixMap(theGWorld);
    SetGWorld(currentPort, currentDevice);
    return;
}


When I step through the program using the source level debugger,
everything works fine with instance1.  When I get to NewGWorld for
instance2, I get
err = 0, theGWorld = NULL and qderr = 0.  If I purposely set the memory
partition for the app too low, I never return from NewGWorld, but I get a
dialog from the TCL telling me that there is not enough memory.  (This I
also do not understand).  The app never really recovers from this and I
have to enter MacsBug and do an ES.  I don't really care about that right
now, I just want to be able to allocate my second GWorld.

Please note: I definitely have enough memory to allocate these two
GWorlds.  They each take a little over 1 MB and I have the memory
partition for the app set to 23 MB (the machine has 32M).  All of this
stuff is right at the beginning of IApplication() so no other large
objects have been created.

Thanks for all the help so far!  Does anybody know what is going on?

Doug Schwarz
Eastman Kodak Company
schwarz@kodak.com

+++++++++++++++++++++++++++

>From Jaeger@fquest.com (Brian Stern)
Date: 25 Aug 1994 05:25:14 GMT
Organization: The University of Texas at Austin, Austin, Texas

In article <schwarz-2408941626470001@150.220.61.78>, schwarz@kodak.com
(Doug Schwarz) wrote:

> I wrote a small application containing little more than my original code
> fragment and I also get a result of -108 when there is not enough memory. 
> It never returns a null GWorld and a zero error.  So, it seems that I need
> to give a more complete description of my original problem.
> 
> When I step through the program using the source level debugger,
> everything works fine with instance1.  When I get to NewGWorld for
> instance2, I get
> err = 0, theGWorld = NULL and qderr = 0.  If I purposely set the memory
> partition for the app too low, I never return from NewGWorld, but I get a
> dialog from the TCL telling me that there is not enough memory.  (This I
> also do not understand).  The app never really recovers from this and I
> have to enter MacsBug and do an ES.  I don't really care about that right
> now, I just want to be able to allocate my second GWorld.
> 
> Please note: I definitely have enough memory to allocate these two
> GWorlds.  They each take a little over 1 MB and I have the memory
> partition for the app set to 23 MB (the machine has 32M).  All of this
> stuff is right at the beginning of IApplication() so no other large
> objects have been created.
> 
> Thanks for all the help so far!  Does anybody know what is going on?
> 
> Doug Schwarz
> Eastman Kodak Company
> schwarz@kodak.com

Hi Doug,

Guess what.  You are successfully creating two GWorlds.  That's why your
return values are err = 0, and qderr = 0.  The problem is that the
GWorldPtr isn't going where you think it is.  In TCL 1.1.3 objects are
handles and your instance variables can move when you call a toolbox
routine that can move memory, like NewGWorld.  You have two choices.  Use
local variables when you need to pass by reference and copy the result to
your instance variables or else lock the object using the utility routine
'Lock'.

The problem you mention with the TCL not enough mem error msg is because
TCL has a GrowZone proc.  If it can't free up enough mem to satisfy the
request it throws an exception.  This includes a longjump out of the trap
that was requesting memory.  I think that this can screw up everything, as
you discovered.

-- 
Brian  Stern  :-{)}
Jaeger@fquest.com

+++++++++++++++++++++++++++

>From python@world.std.com (Steven J. Bushell)
Date: Thu, 25 Aug 1994 11:44:02 -0500
Organization: Kodak Electronic Printing Systems, Inc.

In article <schwarz-2408941626470001@150.220.61.78>, schwarz@kodak.com
(Doug Schwarz) wrote:

> void COffscreenPixMap::IOffscreenPixMap(Rect boundsRect)
> {
>     QDErr           err, qderr;
>     PixMapHandle    pixBase;
>     
>     GetGWorld(&currentPort, &currentDevice);
>     err = NewGWorld(&theGWorld, 32, &boundsRect, NULL, NULL, 0);
>     qderr = QDError();
>     pixBase = GetGWorldPixMap(theGWorld);
>     SetGWorld(currentPort, currentDevice);
>     return;
> }
> Thanks for all the help so far!  Does anybody know what is going on?

Have you tried locking your object before creating the GWorld?  If you
don't, the address of 'theGWorld' can become invalid if memory moves
around (i.e., when creating a new GWorld), and the pointer to the GWorld
will be stored in some random place in memory.  Remember, TCL 1.1.3 is
still handle-based so you have to watch out when using addresses of
instance vars; TCL 2.0 is pointer based so you can avoid these problems if
you use a newer TCL.

- Steve

//////////
//
//   Steve Bushell
//   python@world.std.com
//
//   "It's always the quiet ones."
//
//////////

+++++++++++++++++++++++++++

>From schwarz@kodak.com (Doug Schwarz)
Date: Thu, 25 Aug 1994 17:26:03 GMT
Organization: Eastman Kodak Company, Rochester, NY

In article <Jaeger-2508940027100001@slip-11-9.ots.utexas.edu>,
Jaeger@fquest.com (Brian Stern) wrote:

> Guess what.  You are successfully creating two GWorlds.  That's why your
> return values are err = 0, and qderr = 0.  The problem is that the
> GWorldPtr isn't going where you think it is.  In TCL 1.1.3 objects are
> handles and your instance variables can move when you call a toolbox
> routine that can move memory, like NewGWorld.  You have two choices.  Use
> local variables when you need to pass by reference and copy the result to
> your instance variables or else lock the object using the utility routine
> 'Lock'.
> 
> The problem you mention with the TCL not enough mem error msg is because
> TCL has a GrowZone proc.  If it can't free up enough mem to satisfy the
> request it throws an exception.  This includes a longjump out of the trap
> that was requesting memory.  I think that this can screw up everything, as
> you discovered.
> 
> -- 
> Brian  Stern  :-{)}
> Jaeger@fquest.com


In article <python-2508941144020001@155.50.26.175>, python@world.std.com
(Steven J. Bushell) wrote:

> Have you tried locking your object before creating the GWorld?  If you
> don't, the address of 'theGWorld' can become invalid if memory moves
> around (i.e., when creating a new GWorld), and the pointer to the GWorld
> will be stored in some random place in memory.  Remember, TCL 1.1.3 is
> still handle-based so you have to watch out when using addresses of
> instance vars; TCL 2.0 is pointer based so you can avoid these problems if
> you use a newer TCL.
> 
> - Steve
> 
> //   Steve Bushell
> //   python@world.std.com



Yes!  Brian and Steve are correct.  I replaced

    err = NewGWorld(&theGWorld, 32, &boundsRect, NULL, NULL, 0);

where theGWorld is an instance variable, with

    GWorldPtr    tempGWorld;
    err = NewGWorld(&tempGWorld, 32, &boundsRect, NULL, NULL, 0);
    theGWorld = tempGWorld;

where tempGWorld is a local variable and it works just fine.  I was also able to
make some other simplifications once *that* was working (thanks to some other
helpful suggestions).

So, THANK YOU EVERYBODY and especially Brian and Steve!

Doug Schwarz
Eastman Kodak Company
schwarz@kodak.com

---------------------------

>From partingt@fwi.uva.nl (Vincent Partington)
Subject: Won't strange windows come in my layer?
Date: 23 Aug 1994 11:09:43 GMT
Organization: FWI, University of Amsterdam

Hi everyone,

I'm investigating putting a pointer to an object in the refCon of a windowPtr
to call a virtual function (C++) through it. I was wondering:
Can I be sure I'll only get events for my own windows? Can I be sure the
refCon value doesn't contain garbage?
I know under System 6 DA's would invade your window list but they can be
recognized by looking at the windowKind (or something). It's it ok for my
app to break if somebody makes an INIT that puts windows in my layer?

Thanks, Vincent
-- 
appel peer banaan baksteen           ||| The Fingerware Project:
schelp zon zand rolstoel             ||| Put your code snippets in your .plan!
groen wit geel flatgebouw            ||| If you want to know more
boer postbode bouwvakker roos        ||| finger partingt@gene.fwi.uva.nl

+++++++++++++++++++++++++++

>From Jaeger@fquest.com (Brian Stern)
Date: 23 Aug 1994 16:44:50 GMT
Organization: The University of Texas at Austin, Austin, Texas

In article <33cldn$ncd@hermes.fwi.uva.nl>, partingt@fwi.uva.nl (Vincent
Partington) wrote:

> Hi everyone,
> 
> I'm investigating putting a pointer to an object in the refCon of a windowPtr
> to call a virtual function (C++) through it. I was wondering:
> Can I be sure I'll only get events for my own windows? Can I be sure the
> refCon value doesn't contain garbage?
> I know under System 6 DA's would invade your window list but they can be
> recognized by looking at the windowKind (or something). It's it ok for my
> app to break if somebody makes an INIT that puts windows in my layer?
> 
> Thanks, Vincent
> -- 
> appel peer banaan baksteen           ||| The Fingerware Project:
> schelp zon zand rolstoel             ||| Put your code snippets in your .plan!
> groen wit geel flatgebouw            ||| If you want to know more
> boer postbode bouwvakker roos        ||| finger partingt@gene.fwi.uva.nl

Vincent,

You should set the WindowKind of any window when you create it; choose
values that are not among the already defined values (> 8 I think).  Then
when you receive window events you check the windowkind first and then act
accordingly.  You can put anything you like in the refcon, including
object references.  If you do this then presumably you wouldn't do
anything for a windowkind that your app doesn't know about.

I wouldn't worry about an INIT putting windows in your layer.  If I was
writing an INIT to do such a thing I'd be sure to steal any window events
related to that window before your app ever saw them.

-- 
Brian  Stern  :-{)}
Jaeger@fquest.com

+++++++++++++++++++++++++++

>From jonasw@lysator.liu.se (Jonas Wallden)
Date: 23 Aug 1994 21:02:05 GMT
Organization: (none)

Jaeger@fquest.com (Brian Stern) writes:

>In article <33cldn$ncd@hermes.fwi.uva.nl>, partingt@fwi.uva.nl (Vincent
>Partington) wrote:

>> Hi everyone,
>> 
>> I'm investigating putting a pointer to an object in the refCon of a windowPtr
>> to call a virtual function (C++) through it. I was wondering:
>> Can I be sure I'll only get events for my own windows? Can I be sure the
>> refCon value doesn't contain garbage?
>> I know under System 6 DA's would invade your window list but they can be
>> recognized by looking at the windowKind (or something). It's it ok for my
>> app to break if somebody makes an INIT that puts windows in my layer?
>> 
>> Thanks, Vincent
>> -- 
>> appel peer banaan baksteen         ||| The Fingerware Project:
>> schelp zon zand rolstoel           ||| Put your code snippets in your .plan!
>> groen wit geel flatgebouw          ||| If you want to know more
>> boer postbode bouwvakker roos      ||| finger partingt@gene.fwi.uva.nl
>
>Vincent,
>
>You should set the WindowKind of any window when you create it; choose
>values that are not among the already defined values (> 8 I think).  Then
>when you receive window events you check the windowkind first and then act
>accordingly.  You can put anything you like in the refcon, including
>object references.  If you do this then presumably you wouldn't do
>anything for a windowkind that your app doesn't know about.
>
>I wouldn't worry about an INIT putting windows in your layer.  If I was
>writing an INIT to do such a thing I'd be sure to steal any window events
>related to that window before your app ever saw them.
>
>Brian  Stern  :-{)}

A great way to extend WindowRecords is to declare your own data type with
a WindowRecord as the first item.

E.g.,

struct tMyWinData {
   //  This must come first!
   WindowRecord   winRec;

   //  Additional window-specific data here...
   Handle         aHandle;
   Ptr            aPtr;
};
typedef struct tMyWinData tMyWinData;
typedef tMyWinData *tMyWinPtr;

The trick now is that you can typecast any window pointer to tMyWinPtr (and
back) and access your window-specific data fields. You might want to place
your application's unique creator code in the WindowRecord refCon field and
check it first to be sure you have a window that belongs to your program.

I use this all the time and it is useful in many other places where the
system gives you a pointer to an object (VBL tasks, ParamBlocks, ...) and
you need to store extra data. No need to use any globals for this stuff!

--
`.`.   Jonas Wallden                    `.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.
`.`.`.   Internet: jonasw@lysator.liu.se  `.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.
`.`.`.`.   AppleLink: sw1369                `.`.`.`.`.`.`.`.`.`.`.`.`.`.`.

+++++++++++++++++++++++++++

>From benh@fdn.org (Benjamin Herrenschmidt)
Date: Tue, 23 Aug 94 17:24:09 +0100
Organization: (none)


In article <33cldn$ncd@hermes.fwi.uva.nl> (comp.sys.mac.programmer), partingt@fwi.uva.nl (Vincent Partington) writes:

>I'm investigating putting a pointer to an object in the refCon of a windowPtr
>to call a virtual function (C++) through it. I was wondering:
>Can I be sure I'll only get events for my own windows? Can I be sure the
>refCon value doesn't contain garbage?
>I know under System 6 DA's would invade your window list but they can be
>recognized by looking at the windowKind (or something). It's it ok for my
>app to break if somebody makes an INIT that puts windows in my layer?

I think you should have somewhere a list of YOUR windows, so you can
check it's one of yours before using it's refcon. Another way to do
so is to use a custom windowKind and check for it (that's what PowerPlant
does) but you are not protected against someone using the same windowKind
(there is no way to register them).

BenH.

+++++++++++++++++++++++++++

>From lsr@taligent.com (Larry Rosenstein)
Date: Tue, 23 Aug 1994 23:04:25 GMT
Organization: Taligent, Inc.

In article <33cldn$ncd@hermes.fwi.uva.nl>, partingt@fwi.uva.nl (Vincent
Partington) wrote:

> Can I be sure I'll only get events for my own windows? Can I be sure the
> refCon value doesn't contain garbage?

No.  For example, there's a program called PacerForum (a BBS app) that can
pop up notification windows inside your application's space.  It makes the
windows look like DAs (negative windowKind) so if you handle those
properly you should be OK.

-- 
Larry Rosenstein
Taligent, Inc.

lsr@taligent.com

+++++++++++++++++++++++++++

>From h+@nada.kth.se (Jon W{tte)
Date: Wed, 24 Aug 1994 10:23:51 +0200
Organization: Royal Institute of Something or other

In article <33cldn$ncd@hermes.fwi.uva.nl>,
partingt@fwi.uva.nl (Vincent Partington) wrote:

>It's it ok for my
>app to break if somebody makes an INIT that puts windows in my layer?

Yes; PowerPlant, TCL and MacApp all put object pointers in the 
refCon. To be really safe, set the windowKind of windows you 
create to something >8, like 11147, and test for that first. 
Also test that the object pointer is not 0 (and if you're 
paranoid; not odd and above your heap start and below your 
stack base)

Cheers,

				/ h+


--
  Jon Wätte (h+@nada.kth.se), Hagagatan 1, 113 48 Stockholm, Sweden
 "Don't use the Layer Manager"


+++++++++++++++++++++++++++

>From h+@nada.kth.se (Jon W{tte)
Date: Wed, 24 Aug 1994 23:10:45 +0200
Organization: Royal Institute of Something or other

In article <01050105.7vo9pz@tatooine.fdn.org>,
benh@fdn.org (Benjamin Herrenschmidt) wrote:

>I think you should have somewhere a list of YOUR windows, so you can
>check it's one of yours before using it's refcon. Another way to do
>so is to use a custom windowKind and check for it (that's what PowerPlant
>does) but you are not protected against someone using the same windowKind
>(there is no way to register them).

No, but there is simply NO WAY that someone elses window gets 
into your window list, unless that's a DA/system window, in 
which case the windowKind will be negative. Using a separate 
list is just a lot of trouble to avoid something which won't 
happen; sort of lugging around a portable bomb shelter in case 
a meteorite would hit you...

Cheers,


				/ h+


--
  Jon Wätte (h+@nada.kth.se), Hagagatan 1, 113 48 Stockholm, Sweden
 "Don't use the Layer Manager"


+++++++++++++++++++++++++++

>From sigurasg@plusplus.is (Sigurdur Asgeirsson)
Date: 25 Aug 1994 09:03:27 GMT
Organization: Plusplus Inc.

h+@nada.kth.se (Jon W{tte) writes:

>In article <01050105.7vo9pz@tatooine.fdn.org>,
>benh@fdn.org (Benjamin Herrenschmidt) wrote:

>>I think you should have somewhere a list of YOUR windows, so you can

[snip]

>No, but there is simply NO WAY that someone elses window gets 
>into your window list, unless that's a DA/system window, in 
>which case the windowKind will be negative. Using a separate 
>list is just a lot of trouble to avoid something which won't 
>happen; sort of lugging around a portable bomb shelter in case 
>a meteorite would hit you...

  Uhm, hate to rain on your parade, but what about CTB windows? CTB
tools are allowed to put up windows (just about anytime if I remember
correctly), AND they use the RefCon for their own purposes, so if
you're using the CTB beware...

--
Sigurdur Asgeirsson    | "Well you know, C isn't that hard, void (*(*f[])())()
Kambasel 26            | for instance declares f as an array of unspecified 
109 Reykjavik, Iceland | size, of pointers to functions that return pointers to
sigurasg@plusplus.is   | functions that return void... I think"

---------------------------

End of C.S.M.P. Digest
**********************