From: pottier@clipper.ens.fr (Francois Pottier)
Subject: csmp-digest-v3-053
Date: Mon, 5 Sep 1994 15:28:25 +0200 (MET DST)

C.S.M.P. Digest             Mon, 05 Sep 94       Volume 3 : Issue 53
 
Today's Topics:
 
        A real funny story
        AppleScript: event times out
        C++ Virtual Destructor Q
        Enum size -- what's the LCD?
        Followup on 'Safe Save' problem - still ticking!
        MW DebugNew Tip
        Scrollbars in Dialogs?
        Should new programs still be System 6 compatible?
        The System 7.5 Think Debugger Bug - and fix!
        Think Debugger & INIT source code
        [Q] How to do non-bypassable INIT?
        malloc problem in CW-4



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 nick+@pitt.edu ( nick.c )
Subject: A real funny story
Date: Fri, 19 Aug 94 21:40:04 GMT
Organization: The Pitt, Chemistry


Folks:

    A friend of mine just sent me this, personally I think it's
      hilarious (so long as you don't work for MS :-).  Enjoy,


- --


"Star Trek Lost Episodes" transcript.

<Picard> "Mr. LaForge, have you had any success with your
attempts at finding a weakness with the Borg?  And Mr. Data,
have you been able to access their command pathways?"

<Geordi> "Yes, Captain.  In fact, we found the answer by
searching through our archives on late twentieth-century
computing technology."

<Geordi presses a key, and a logo appears on the computer
screen.>

<Riker looks puzzled.> "What the hell is 'Microsoft'?"

<Data turns to answer.> "Allow me to explain.  We will send
this program, for some reason called 'Windows,' through
the Borg command pathways.  Once inside their root com-
mand unit, it will begin consuming system resources at an
unstoppable rate."

<Picard> "But the Borg have the ability to adapt.  Won't
they alter their processing systems to increase their storage
capacity?"

<Data> "Yes, Captain.  But when 'Windows' detects this, it
will create a new version of itself called an 'upgrade.'  The
use of resources increases exponentially with each iteration.
The Borg will not be able to adapt quickly enough.
Eventually all of their processing ability will be taken over
and none will be available for their normal operational
functions."

<Picard> "Excellent work.  This is even better than that
'unsolvable geometric shape' idea."

<. . . 15 minutes later . . .>

<Data> "Captain, we have successfully installed the
'Windows' in the command unit and, as expected, it
immediately consumed 85% of all resources.  We, however,
have not received any confirmation of the expected
'upgrade.'"

<Geordi> "Our scanners have picked up an increase in Borg
storage and CPU capacity to compensate, but we still have no
indication of an 'upgrade' to compensate for their increase."

<Picard> "Data, scan the history books again and determine
if there is something we have missed."

<Data> "Sir, I believe there is a reason for the failure in the
'upgrade.'  Apparently the Borg have circumvented that part
of the plan by not sending in their 'registration cards.'"

<Riker>  "Captain, we have no choice.  Requesting
permission to begin emergency escape sequence 3F . . ."

<Geordi, excited>  "Wait, Captain, I just detected that their
CPU capacity has suddenly dropped to 0%!"

<Picard> "Data, what do your scanners show?"

<Data> "Apparently the Borg have found the internal
'Windows' module named 'solitaire' and it has used up all
the CPU capacity."

<Picard> "Let's wait and see how long this 'solitaire' can
reduce their functionality."

<. . . Two hours pass . . .>

<Riker> "Geordi, what's the status of the Borg?"

<Geordi> "As expected the Borg are attempting to re-
engineer to compensate for increased CPU and storage
demands, but each time they successfully increase resources
I have set up our closest deep space monitor beacon to
transmit more 'Windows' modules from something called
the 'Microsoft fun-pack.'"

<Picard> "How much time will that buy us?"

<Data> "Current Borg solution rates allow me to predict an
interest time span of 6 more hours."

<Geordi> "Captain, another vessel has entered our sector."

<Picard> "Identify."

<Data> "It appears to have markings similar to the
'Microsoft' logo."

<Over the speakers> "THIS IS ADMIRAL BILL GATES
OF THE MICROSOFT FLAGSHIP MONOPOLY.  WE
HAVE POSITIVE CONFIRMATION OF UN-
REGISTERED SOFTWARE IN THIS SECTOR.
SURRENDER ALL ASSETS AND WE CAN AVOID ANY
TROUBLE.  YOU HAVE TEN SECONDS."

<Data> "The alien ship has just opened its forward hatches
and released thousands of humanoid shaped objects."

<Picard> "Magnify forward viewer on the alien craft."

<Riker> "Good God Captain!  Those are humans floating
straight toward the Borg ship with no life support suits!
How can they survive the tortures of deep space?!"

<Data> "I do not believe that those are humans sir; if you will
look closer, I believe you will see that they are carrying
something recognized in the twenty-first century as doe-skin
leather briefcases, and wearing Armani suits."

<Riker and Picard together horrified> "Lawyers!!"

<Geordi> "It can't be.  All the lawyers were rounded up and
sent hurtling into the sun in 2017 during the great awaken-
ing."

<Data> "True, but apparently some must have survived."

<Riker> "They have surrounded the Borg ship and are
covering it with all types of papers."

<Data> "I believe that is known in ancient vernacular as 'red
tape.'  It often proves fatal.

<Riker> "They're tearing the Borg to pieces!"

<Picard> "Turn off the monitors.  I can't stand to watch.  Not
even the Borg deserve that."



  Disclaimer: Just my opinion.
                                    _/   _/  _/  _/_/_/   _/   _/  
     Interet: nick@pitt.edu        _/_/ _/  _/  _/   _/  _/_/_/    
      eWorld: nick                _/ _/_/  _/  _/       _/ _/      
         CIS: 71232,766          _/   _/  _/   _/_/_/  _/   _/     
    
           "Science is nothing but perception" - Plato

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

>From kocher@lts.sel.alcatel.de (Hartmut Kocher US/ESA 60/1L/2? #5629)
Subject: AppleScript: event times out
Date: Mon, 22 Aug 94 08:33:35 GMT
Organization: SEL-Alcatel LTS Dept. US/ES

I've written a small AppleScript, that copies a few folders around
using the scriptable Finder. My problem is that if one of these folders
holds many files, the reply from the Finder takes too long and the
reply times out (aborting the script :-( ).

How can I set the timeout value, so my script is willing to wait
longer fro a reply?

Thanks for your suggestions.

-- 
+==============================|==============================+
| Hartmut Kocher               |                              |
| Technical Consultant         | All opinions expressed here  |
| Rational GmbH                | are my own.                  |
| Rosenstrasse 7               |                              |
| 82049 Pullach im Isartal     | I know you guessed it,       |
| Germany                      | but it keeps my lawyer happy.|
| Email: hwk@rational.com      |                              |
+==============================|==============================+

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

>From dmcleod@hpb.hwc.ca (D.A. McLeod)
Date: 22 Aug 1994 13:32:42 GMT
Organization: Health Canada

Hartmut Kocher US/ESA 60/1L/2? #5629 (kocher@lts.sel.alcatel.de) wrote:
: How can I set the timeout value, so my script is willing to wait
: longer fro a reply?

with timeout of #### seconds
     .
     .
     .
end timeout

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

>From engelhar@bga.com (Michael Engelhart)
Date: 22 Aug 1994 15:38:09 GMT
Organization: Apple Travel

In article <1994Aug22.083335.25853@lts.sel.alcatel.de>,
kocher@lts.sel.alcatel.de (Hartmut Kocher US/ESA 60/1L/2? #5629) wrote:

> I've written a small AppleScript, that copies a few folders around
> using the scriptable Finder. My problem is that if one of these folders
> holds many files, the reply from the Finder takes too long and the
> reply times out (aborting the script :-( ).
> 
> How can I set the timeout value, so my script is willing to wait
> longer fro a reply?
> 
> Thanks for your suggestions.
> 
> -- 
> +==============================|==============================+
> | Hartmut Kocher               |                              |
> | Technical Consultant         | All opinions expressed here  |
> | Rational GmbH                | are my own.                  |
> | Rosenstrasse 7               |                              |
> | 82049 Pullach im Isartal     | I know you guessed it,       |
> | Germany                      | but it keeps my lawyer happy.|
> | Email: hwk@rational.com      |                              |
> +==============================|==============================+


Hartmut,

simply enclose your routine with the following:

with timeout of 400 seconds --use any value you want, the default is 120
seconds
 	your routine
end timeout

Mike

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

>From jpek@umich.edu (Jeff Pek)
Subject: C++ Virtual Destructor Q
Date: 19 Aug 1994 22:05:08 GMT
Organization: U of Mich (MBA)

I wonder if someone could clear the air around our office about why
virtual destructors should or should not be used. Specifically, I'm
interested in Metrowerks' compiler's implementation.

1) Why would I want to/need to declare a destructor virtual?
2) What happens if I don't?

Thanks very much!
Jeff

- -------------------------------------------
Jeff Pek                       jpek@umich.edu
Emerald Intelligence / University of Michigan

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

>From mwron@aol.com (MW Ron)
Date: 19 Aug 1994 19:44:06 -0400
Organization: America Online, Inc. (1-800-827-6364)

In article <333aak$fj8@lastactionhero.rs.itd.umich.edu>, jpek@umich.edu
(Jeff Pek) writes:

>>1) Why would I want to/need to declare a destructor virtual?
>>2) What happens if I don't?

1) You need to declare a virtual destructor when you have a base class,
its destructor is different than the derived classes destructor, and
objects are deleted via pointer or refernce to base class. ( a good habit,
declare it for all base classes )

2) if you don't, you will not guarantee all objects will be deleted when
an object is deleted, if it is accessed as a base class poiter.
 
Scott Meyers in Effective C++ explains this quite well.

Ron Liechty
RonL@metrowerks.com
Metrowerks Inc.

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

>From neeri@iis.ee.ethz.ch (Matthias Neeracher)
Date: 19 Aug 1994 23:19:32 GMT
Organization: Swiss Federal Institute of Technology (ETHZ)

jpek@umich.edu (Jeff Pek) writes:
>I wonder if someone could clear the air around our office about why
>virtual destructors should or should not be used. Specifically, I'm
>interested in Metrowerks' compiler's implementation.

>1) Why would I want to/need to declare a destructor virtual?

As a rule of thumb, as soon as you have a virtual function for a class,
you should also have a virtual destruction.

>2) What happens if I don't?

As an example, take:

class A ...
class B : public A ...

A * pa = new B;

delete pa;

Unless A has a virtual destructor, no destructor for B will be executed on the
object pointed to by pa, which is would often be desirable.

Matthias

- ---
Matthias Neeracher <neeri@iis.ee.ethz.ch> http://err.ethz.ch/members/neeri.html
   "There once was an Age of Reason, but we've progressed beyond it."
                                   -- Ayn Rand, _Atlas Shrugged_

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

>From gurgle@dnai.com (Pete Gontier)
Date: Fri, 19 Aug 1994 20:17:34 -0800
Organization: Integer Poet Software

In article <333aak$fj8@lastactionhero.rs.itd.umich.edu>, jpek@umich.edu
(Jeff Pek) wrote:

> 1) Why would I want to/need to declare a (C++) destructor virtual?
> 2) What happens if I don't?

The Annotated C++ Reference Manual (commonly known as "the ARM"), Ellis
and Stroustup, ISBN, 0-201-51459-1, chapter 12.4 (page 276 in my
printing).

And a note to aid in your reading: non-virtual destructors are the
exception (no pun intended), not the rule.

-- 
 Pete Gontier // CTO, Integer Poet Software // gurgle@dnai.com

 "Even during a particularly harsh (Colorado) winter... many of the
 300 families in the VCTV (movies-on-demand) trial continued to go
 to video stores." -- eis@murrow.tufts.edu, in Wired 2.09 p62

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

>From mwron@aol.com (MW Ron)
Date: 20 Aug 1994 12:20:01 -0400
Organization: America Online, Inc. (1-800-827-6364)

In article <gurgle-1908942017340001@gurgle.dnai.com>, gurgle@dnai.com
(Pete Gontier) writes:

Here is a short example of a virtual destructor in use. remove the virtual
keyword and you will see that only the base class's destructor is called.
Ron Liechty
RonL@metrowerks.com
Metrowerks Inc.

#include <iostream>

class base {
  public:
     int *a;
  protected:
     base() { a = new int(1);}
  public:
     virtual ~base()  { cout << "deleteting base "; delete a;};
};

class base2 : public base {
  public:
      int *b;
  protected:
      base2() { b = new int(1);}
  public:
      virtual ~base2()  { cout << "deleteting base2 "; delete b;};
 };
 
 class d : public base2 {
     public :
       int *c;
     public:
       d() { c = new int(3);}
       ~d() { cout << "deleteting d "; delete c;};
 };    
      
      
 main()
 {
    base *bPtr = new d;
    delete bPtr;
    
    cout << "enter a char " ;
    cin.get();   
    return 0;
 }     
      

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

>From ekstrom@aggroup.com (Harold Ekstrom)
Date: Sat, 20 Aug 1994 20:45:15 -0800
Organization: Ag Group

In article <333g46$hu5@search01.news.aol.com>, mwron@aol.com (MW Ron) wrote:

> In article <333aak$fj8@lastactionhero.rs.itd.umich.edu>, jpek@umich.edu
> (Jeff Pek) writes:
> 
> >>1) Why would I want to/need to declare a destructor virtual?
> >>2) What happens if I don't?
> 
> 1) You need to declare a virtual destructor when you have a base class,
> its destructor is different than the derived classes destructor, and
> objects are deleted via pointer or refernce to base class. ( a good habit,
> declare it for all base classes )
> 
> 2) if you don't, you will not guarantee all objects will be deleted when
> an object is deleted, if it is accessed as a base class poiter.
>  
> Scott Meyers in Effective C++ explains this quite well.
> 
> Ron Liechty
> RonL@metrowerks.com
> Metrowerks Inc.

Another good source of answers for this and other common C++
questions is the C++FAQ (rtfm.mit.edu). It was one of the
first things I read when learning C++.

harold
- ------------------------------------------------------------
Harold Ekstrom
ekstrom@aggroup.com
ag group, inc.
2540 camino diablo, suite 200
walnut creek, ca 94596
510-937-7900 voice
510-937-2479 fax
510-937-6704 ara
ftp.aggroup.com anonymous ftp
 

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

>From afrancke@netcom.com (Andrew Francke)
Subject: Enum size -- what's the LCD?
Date: Wed, 17 Aug 1994 02:54:56 GMT
Organization: Netcom Online Communications Services (408-241-9760 login: guest)

If I'm not mistaken, the lowest common denominator for enum size is
that presented by MPW 68k C -- variable 1, 2, or 4 bytes. Other Mac C
and C++ compilers support the ANSI definition, sizeof(enum) ==
sizeof(int), but not MPW C. All Mac compilers support variable enum
size just like MPW C.

Is this strictly correct?

Now, examine the following code:

typedef enum
{
	a=255
} one_byte_enum_t;

typedef enum
{
	b=65000
} two_byte_enum_t;

typedef enum
{
	c=1000000
} three_byte_enum_t;

#if defined (powerc) || defined (__power)
#pragma align=mac68k
#endif
struct test1
{
	one_byte_enum_t		mem1;
	two_byte_enum_t		mem2;
	three_byte_enum_t	mem3;
};
#if defined (powerc) || defined (__powerc)
#pragma align reset // or whatever it is
#endif

The $10,000,000 question -- do these structures lay out on every Mac
C compiler in this way:

Offset		Byte
from		Contents
&test 1:
- ---------	--------
0x00000000:	mem1
0x00000001:	<pad>
0x00000002:	mem2
0x00000003:	mem2
0x00000004:	mem3
0x00000005:	mem3
0x00000006:	mem3
0x00000007:	mem3

How about stack alignment? If I declare a function:

void
foo ( one_byte_enum a, two_byte_enum b, three_byte_enum c );

...what will the stack look like? Will it be the same for all Mac C/C++
compilers?

Example stack:
         1   2   3   4   5   6   7   8
SP-0x8:  c   c   c   c   b   b <pad> a
SP:

(Sorry if this last example isn't that clear -- the stack is being
displayed in hi-lo, left to right order, assuming that all parameters
have been pushed and we're about to JSR to foo)

Thanks in advance for your insight.

Andy Francke

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

>From mclow@san_marcos.csusm.edu (Marshall Clow)
Date: Wed, 17 Aug 1994 00:53:32 -0800
Organization: Aladdin Systems

In article <afranckeCuns3L.MuC@netcom.com>, afrancke@netcom.com (Andrew
Francke) wrote:

> If I'm not mistaken, the lowest common denominator for enum size is
> that presented by MPW 68k C -- variable 1, 2, or 4 bytes. Other Mac C
> and C++ compilers support the ANSI definition, sizeof(enum) ==
> sizeof(int), but not MPW C. All Mac compilers support variable enum
> size just like MPW C.
> 
> Is this strictly correct?
>
   No. It's wrong in several areas.

> 
[ code deleted ]
> 
> The $10,000,000 question -- do these structures lay out on every Mac
> C compiler in this way:
> 
[ more code deleted ]

No. Different compilers allocated sizes for enums differently. I believe
that the following is true:

1) MPW C (68K) -- enums are 4 bytes

2) Think C (68K) -- enums are 1, 2, or 4 bytes (based on values) except if
the "Enums are always ints" preference is checked, in which case they are
2 or 4 bytes depending on how big your ints are.

3) Metrowerks C (68K) -- same as Think C (68K).

4) Metrowerks C (PPC) -- enums are 1, 2, or 4 bytes (based on values)
except if the "Enums are always ints" preference is checked, in which case
they are 4 bytes.

5) PPCC (Apple's MPW based PPC compiler) -- I don't know.
6) Apple's new PPC C compiler (Beta on ETO #15) -- I don't know
7) Motorola C (PPC) -- I don't know
8) Absoft C (PPC) -- I don't know

[ I'm sure I forgot someone. ]

The ANSI spec (from memory, so don't flame me for wordage) says that enums
must be "compatible with integer type". The rest is up to the compiler
writer.

This is one of the non-portable aspects of C.

-- Marshall

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

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

>From becker@Xenon.Stanford.EDU (Denizen of the Deep)
Date: 17 Aug 1994 16:22:16 GMT
Organization: Computer Science Department, Stanford University.

In article <mclow-1708940053320001@lpm8.csusm.edu>,
Marshall Clow <mclow@san_marcos.csusm.edu> wrote:
>
>The ANSI spec (from memory, so don't flame me for wordage) says that enums
>must be "compatible with integer type". The rest is up to the compiler
>writer.
>
>This is one of the non-portable aspects of C.
>
>-- Marshall
>

>From K&R II, A8.4:
	The identifiers in an enumerator list are declared as constants
	of type int...

So there you have it.  In strict ANSI C, enums should take up the same
space as an int on the machine (i.e. 2 or 4 bytes, depending on your
settings and/or compiler).  It's only non-portable in the sense that
different compilers may have different sizes for int; however once the
choice of int size is made, there is no latitude for choosing how to
deal with enums.

-Jon

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

>From Lars.Farm@nts.mh.se (Lars Farm)
Date: Fri, 19 Aug 1994 10:08:12 +0100
Organization: Mid Sweden University

In article <32tdfo$gn2@Times.Stanford.EDU>, becker@Xenon.Stanford.EDU
(Denizen of the Deep) wrote:

> From K&R II, A8.4:
>         The identifiers in an enumerator list are declared as constants
>         of type int...
> 
> So there you have it.  In strict ANSI C, enums should take up the same
> space as an int on the machine (i.e. 2 or 4 bytes, depending on your

In C perhaps, but not so in C++. enum is not int. An enum can be
initialized by a constant expression of integral type. An enum will
silently be converted to an int where an int is expected (|, &, + ...) but
an int will not silently be converted to an enum, because nothing says it
will fit in the space allocated for the enum. Cast needed.

An enum is required to have room for "...the nearest larger binary power
minus 1 and down to 0...". So enum { false,true } is only required to
allocate one bit for the value. [ARM - ANSI/ISO resolutions r.7.2].
Realistically this means that an enum will be allocated 1, 2 or 4 bytes
depending on enumerated constants and whatever the compilers author sees
reasonable. In any event the space allocated to an enum may be smaller
than what is needed for an int provided it has room for any of the enum
constants.

Lars

-- 
Lars.Farm@nts.mh.se

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

>From phils@bedford.symantec.com (Phil Shapiro)
Date: Fri, 19 Aug 1994 12:36:51 -0400
Organization: Symantec Corp.

| No. Different compilers allocated sizes for enums differently. I believe
| that the following is true:

Only slightly off, with respect to "enums are always ints", see below*.

| 1) MPW C (68K) -- enums are 4 bytes
| 
| 2) Think C (68K) -- enums are 1, 2, or 4 bytes (based on values) except if
| the "Enums are always ints" preference is checked, in which case they are
| 2 or 4 bytes depending on how big your ints are.
| 
| 3) Metrowerks C (68K) -- same as Think C (68K).
| 
| 4) Metrowerks C (PPC) -- enums are 1, 2, or 4 bytes (based on values)
| except if the "Enums are always ints" preference is checked, in which case
| they are 4 bytes.
| 
| 5) PPCC (Apple's MPW based PPC compiler) -- I don't know.
| 6) Apple's new PPC C compiler (Beta on ETO #15) -- I don't know
| 7) Motorola C (PPC) -- I don't know
| 8) Absoft C (PPC) -- I don't know

9) Symantec C/C++ -- enums are 1, 2, or 4 bytes based on values. If enums
are always ints is checked, then they are 4 bytes. The rules are the same
for both the 68k and PowerPC compilers.

Apple's new PPC C++ compiler (aka MrC) should be the same as Symantec C++,
since they share compiler front ends.

(*) In ANSI C, enums are the same size as int, provided that the value
that they contain can be represented in an int. So when you use the "enums
are always ints" option, you're really saying that they're at least as big
as an int. They can be bigger, or unsigned (or both), depending on the
value that they contain.

The main thing is that you shouldn't depend on the size of an enum. If you
plan to do I/O with an enum, cast it to a known (portable) type first.

   -phil

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

>From afrancke@netcom.com (Andrew Francke)
Date: Fri, 19 Aug 1994 21:16:29 GMT
Organization: Netcom Online Communications Services (408-241-9760 login: guest)

> The main thing is that you shouldn't depend on the size of an enum. If
> you plan to do I/O with an enum, cast it to a known (portable) type first.
>  -phil

I'm afraid this is a moot point in my case. I've already got a sizable
amount of ASN.1-compiler-generated C source with enums a'plenty in
struture declarations.

I'll state my question again:
GIVEN THE RIGHT SET OF COMPILER OPTIONS, is not the LCD of enum sizes
the 1-2-4 packing scheme? I yet labor under the impression that MPW C
doesn't even support "enums are ints" as an option.

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

>From redial <redial@netcom.com>
Subject: Followup on 'Safe Save' problem - still ticking!
Date: Sat, 20 Aug 1994 21:46:44 GMT
Organization: NETCOM On-line Communication Services (408 261-4700 guest)

Netters -

Thanks to all who attempted to help with my 'Safe save' problem.  It did
indeed look as tho  closing the temporary file after the FSpExchangeFiles
swap would solve the problem of the 'File Busy' error message when I
attempted to delete the temporary file.  Unfortunately :-( it didn't.

Here's a summary of my Safe Save procedure, which follows the example in
Think C Reference 2.0.  I call StandardPutFile to get the user's input re
the new file.  If the reply is good and we're not replacing an existing
file, I call FSpCreate.  (According to IM:Files this creates a file with
both forks, only they're both empty.)  I then call FSpCreateResFile to
open
the resource fork, and proceed to copy a string resource for the
'Application missing' error message ('STR ' ID -16396) from my
application's resources into the new file.  I then close the resouce fork
with an FSClose.  Next, I open the data fork using FSpOpenDF.  If no
errors
occur, I proceed to create a temporary file, open its data fork, write the
data into it, close it, exchange its data with the real file, and then
delete the temporary file.  It's at this point I get my first sign of
trouble: OSErr -47, aka 'File busy.'

My snooping has revealed the following points of information. 1) When I
attempt to open the newly created document file with ResEdit, I'm told it
doesn't have a resource fork.  2) It does contain the appropriate data in
its data fork.  And 3) if I reboot the computer, the temporary file shows
up in the trashcan in a folder labled 'Rescued items.'

>From this, is it obvious to anyone as to what I'm doing wrong?  Any
suggestions on what debugging steps I should take would be greatly
appreciated.

TIA. 

Ron Goebel                     |  Internet: redial@netcom.com

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

>From tgaul@halcyon.com (Troy Gaul)
Date: Sat, 20 Aug 1994 23:05:30 -0700
Organization: Infinity Systems

In article <netnewsCuusHx.25A@netcom.com>, redial <redial@netcom.com> wrote:

> Here's a summary of my Safe Save procedure, which follows the example in
> Think C Reference 2.0.  I call StandardPutFile to get the user's input re
> the new file.  If the reply is good and we're not replacing an existing
> file, I call FSpCreate.  (According to IM:Files this creates a file with
> both forks, only they're both empty.)  I then call FSpCreateResFile to
> open
> the resource fork, and proceed to copy a string resource for the
> 'Application missing' error message ('STR ' ID -16396) from my
> application's resources into the new file.  I then close the resouce fork
> with an FSClose.  Next, I open the data fork using FSpOpenDF.  If no
> errors
> occur, I proceed to create a temporary file, open its data fork, write the
> data into it, close it, exchange its data with the real file, and then
> delete the temporary file.  It's at this point I get my first sign of
> trouble: OSErr -47, aka 'File busy.'

First, it sounds like you're putting the resources into the 'real' file,
and then putting the data into the 'temp' file's data fork, and then doing
a swap on them.  This isn't what you want to do.  The call
FSpExchangeFiles doesn't swap the data fork from one file to another, it
swaps the directory information for the two files.  This means that both
the data and resource forks are swapped.

Note, though, that this call does not swap the Finder information (like
Modification Dates) for the files (or the locations in the file system,
i.e. the file named 'Temp File' is still in the Temporary Items Folder).

Next, once you have exchanged the files, I _think_ that the refnums you
have for the files are also considered 'swapped' (it's been a while since
I've done this, and I don't have the source code I produced anymore, but a
quick glance into the Think Reference seemed to indicate that).  

This means if you have the variables 'realFileRefnum' and
'tempFileRefnum', which point where their names imply before the swap,
after the swap, they point to the opposite files in the files system. So,
by closing tempFileRefnum, you're really closing the 'real' file, and when
you try to delete the file with tempFileFSSpec, the 'temp' file hasn't
been closed, and you'd get that error.  (Note that although the refnums
are backward, the FSSpecs still point to the files that their names would
imply, because these files are still in the same locations in the file
system, just their contents have been swapped.)


> My snooping has revealed the following points of information. 
> 1) When I
> attempt to open the newly created document file with ResEdit, I'm told it
> doesn't have a resource fork.  

That's because you never added a resource fork to the temp file (where you
should have), you added it to the intended destination file (where it was
then swapped into the temp file, the one you find in the Rescued Items
folder).


> 2) It does contain the appropriate data in
> its data fork.  And 

That's because the swap did in fact occur.


> 3) if I reboot the computer, the temporary file shows
> up in the trashcan in a folder labled 'Rescued items.'

Anything in the temporary folder upon restart will be put into a folder by
that name in the Trash automatically.  This is indicative of the fact that
the temp file was never deleted (as your error message indicated).

Hope this helps.
_troy
//////// //////___Troy Gaul____________________tgaul@halcyon.com___//
  //    //      Infinity Systems                                  //
 //    //  //  Redmond, Washington                               //
//    //////____________________________________________________//

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

>From h+@nada.kth.se (Jon W{tte)
Date: Sun, 21 Aug 1994 13:28:06 +0200
Organization: Royal Institute of Something or other

In article <netnewsCuusHx.25A@netcom.com>,
redial <redial@netcom.com> wrote:

>Thanks to all who attempted to help with my 'Safe save' problem.  It did
>indeed look as tho  closing the temporary file after the FSpExchangeFiles
>swap would solve the problem of the 'File Busy' error message when I
>attempted to delete the temporary file.  Unfortunately :-( it didn't.

That's because when you call FSpExchangeFiles, the open file 
reference still points into the data you're writing; i e the 
fRefNum now points into the "real" file and not the "temp" file 
which now contains the old data. You have to close the _old_ 
file!

/*
 * Add error checking to taste
 * This assumes you're passing the address of your currently-
 * open file's fRefNum, and the FSSpec for it, and that there
 * is indeed a currently-open file.
 */
void
SafeSave (
	short * oldRefNum ,
	const FSSpec * fileLocation )
{
	FSSpec tempSpec ;
	short tempRef = 0 ;
	FInfo fi ;

	FSpGetFInfo ( fileLocation , & fi ) ;

	MakeTempSpec ( & tempSpec ) ;
	FSpCreate ( & tempSpec , 'trsh' , 'trsh' , smSystemScript ) ;
	FSpOpenDF ( & tempSpec , fsRdWrPerm , & tempRef ) ;

	WriteDataToFile ( tempRef ) ;

	FSpExchangeFiles ( fileLocation , & tempSpec ) ;
	FSpSetFInfo ( fileLocation , & fi ) ;
	FSClose ( * oldRefNum ) ;
	* oldRefNum = tempRef ;
	FSpDelete ( & tempSpec ) ;
}


--