Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
SampleInit.c
/* |
File: SampleInit.c |
Contains: Sample is an example application that demonstrates how to |
initialize the commonly used toolbox managers, operate |
successfully under MultiFinder, handle desk accessories, |
and create, grow, and zoom windows. |
It does not by any means demonstrate all the techniques |
you need for a large application. In particular, Sample |
does not cover exception handling, multiple windows/documents, |
sophisticated memory management, printing, or undo. All of |
these are vital parts of a normal full-sized application. |
This application is an example of the form of a Macintosh |
application; it is NOT a template. It is NOT intended to be |
used as a foundation for the next world-class, best-selling, |
600K application. A stick figure drawing of the human body may |
be a good example of the form for a painting, but that does not |
mean it should be used as the basis for the next Mona Lisa. |
We recommend that you review this program or TESample before |
beginning a new application. |
SetPort strategy: |
Toolbox routines do not change the current port. In spite of this, in this |
program we use a strategy of calling SetPort whenever we want to draw or |
make calls which depend on the current port. This makes us less vulnerable |
to bugs in other software which might alter the current port (such as the |
bug (feature?) in many desk accessories which change the port on OpenDeskAcc). |
Hopefully, this also makes the routines from this program more self-contained, |
since they don't depend on the current port setting. |
Written by: |
Copyright: Copyright © 1989-1999 by Apple Computer, Inc., All Rights Reserved. |
You may incorporate this Apple sample source code into your program(s) without |
restriction. This Apple sample source code has been provided "AS IS" and the |
responsibility for its operation is yours. You are not permitted to redistribute |
this Apple sample source code as "Apple sample source code" after having made |
changes. If you're going to re-distribute the source, we require that you make |
it clear in the source that the code was descended from Apple sample source |
code, but that you've made changes. |
Change History (most recent first): |
7/9/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1 |
*/ |
#include <OSUtils.h> |
#include <Traps.h> |
#include "Sample.h" /* bring in all the #defines for Sample */ |
/* The "g" prefix is used to emphasize that a variable is global. */ |
/* All are extern since the variables are declared in the main segment. */ |
/* GMac is used to hold the result of a SysEnvirons call. This makes |
it convenient for any routine to check the environment. */ |
extern SysEnvRec gMac; /* set up by Initialize */ |
/* GHasWaitNextEvent is set at startup, and tells whether the WaitNextEvent |
trap is available. If it is false, we know that we must call GetNextEvent. */ |
extern Boolean gHasWaitNextEvent; /* set up by Initialize */ |
/* GInBackground is maintained by our osEvent handling routines. Any part of |
the program can check it to find out if it is currently in the background. */ |
extern Boolean gInBackground; /* maintained by Initialize and DoEvent */ |
/* The following globals are the state of the window. If we supported more than |
one window, they would be attatched to each document, rather than globals. */ |
/* GStopped tells whether the stop light is currently on stop or go. */ |
extern Boolean gStopped; /* maintained by Initialize and SetLight */ |
/* GStopRect and gGoRect are the rectangles of the two stop lights in the window. */ |
extern Rect gStopRect; /* set up by Initialize */ |
extern Rect gGoRect; /* set up by Initialize */ |
/* Set up the whole world, including global variables, Toolbox managers, |
and menus. We also create our one application window at this time. |
Since window storage is non-relocateable, how and when to allocate space |
for windows is very important so that heap fragmentation does not occur. |
Because Sample has only one window and it is only disposed when the application |
quits, we will allocate its space here, before anything that might be a locked |
relocatable object gets into the heap. This way, we can force the storage to be |
in the lowest memory available in the heap. Window storage can differ widely |
amongst applications depending on how many windows are created and disposed. */ |
/* 1.01 - The code that used to be part of ForceEnvirons has been moved into |
this module. If an error is detected, instead of merely doing an ExitToShell, |
which leaves the user without much to go on, we call AlertUser, which puts |
up a simple alert that just says an error occurred and then calls ExitToShell. |
Since there is no other cleanup needed at this point if an error is detected, |
this form of error- handling is acceptable. If more sophisticated error recovery |
is needed, an exception mechanism, such as is provided by Signals, can be used. */ |
void Initialize() |
{ |
Handle menuBar; |
DialogPtr newDialogP; |
long total, contig; |
EventRecord event; |
short count; |
gInBackground = false; |
InitGraf((Ptr) &qd.thePort); |
InitFonts(); |
InitWindows(); |
InitMenus(); |
TEInit(); |
InitDialogs(nil); |
InitCursor(); |
/* Call MPPOpen and ATPLoad at this point to initialize AppleTalk, |
if you are using it. */ |
/* NOTE -- It is no longer necessary, and actually unhealthy, to check |
PortBUse and SPConfig before opening AppleTalk. The drivers are capable |
of checking for port availability themselves. */ |
/* This next bit of code is necessary to allow the default button of our |
alert be outlined. |
1.02 - Changed to call EventAvail so that we don't lose some important |
events. */ |
for (count = 1; count <= 3; count++) |
EventAvail(everyEvent, &event); |
/* Ignore the error returned from SysEnvirons; even if an error occurred, |
the SysEnvirons glue will fill in the SysEnvRec. You can save a redundant |
call to SysEnvirons by calling it after initializing AppleTalk. */ |
SysEnvirons(kSysEnvironsVersion, &gMac); |
/* Make sure that the machine has at least 128K ROMs. If it doesn't, exit. */ |
if (gMac.machineType < 0) AlertUser(); |
/* 1.02 - Move TrapAvailable call to after SysEnvirons so that we can tell |
in TrapAvailable if a tool trap value is out of range. */ |
gHasWaitNextEvent = TrapAvailable(_WaitNextEvent, ToolTrap); |
/* 1.01 - We used to make a check for memory at this point by examining ApplLimit, |
ApplicZone, and StackSpace and comparing that to the minimum size we told |
MultiFinder we needed. This did not work well because it assumed too much about |
the relationship between what we asked MultiFinder for and what we would actually |
get back, as well as how to measure it. Instead, we will use an alternate |
method comprised of two steps. */ |
/* It is better to first check the size of the application heap against a value |
that you have determined is the smallest heap the application can reasonably |
work in. This number should be derived by examining the size of the heap that |
is actually provided by MultiFinder when the minimum size requested is used. |
The derivation of the minimum size requested from MultiFinder is described |
in Sample.h. The check should be made because the preferred size can end up |
being set smaller than the minimum size by the user. This extra check acts to |
insure that your application is starting from a solid memory foundation. */ |
if ((long) GetApplLimit() - (long) ApplicationZone() < kMinHeap) AlertUser(); |
/* Next, make sure that enough memory is free for your application to run. It |
is possible for a situation to arise where the heap may have been of required |
size, but a large scrap was loaded which left too little memory. To check for |
this, call PurgeSpace and compare the result with a value that you have determined |
is the minimum amount of free memory your application needs at initialization. |
This number can be derived several different ways. One way that is fairly |
straightforward is to run the application in the minimum size configuration |
as described previously. Call PurgeSpace at initialization and examine the value |
returned. However, you should make sure that this result is not being modified |
by the scrap's presence. You can do that by calling ZeroScrap before calling |
PurgeSpace. Make sure to remove that call before shipping, though. */ |
/* ZeroScrap(); */ |
PurgeSpace(&total, &contig); |
if (total < kMinSpace) AlertUser(); |
/* The extra benefit to waiting until after the Toolbox Managers have been initialized |
to check memory is that we can now give the user an alert to tell him/her what |
happened. Although it is possible that the memory situation could be worsened by |
displaying an alert, MultiFinder would gracefully exit the application with |
an informative alert if memory became critical. Here we are acting more |
in a preventative manner to avoid future disaster from low-memory problems. */ |
newDialogP = GetNewDialog(rWindow, nil, (WindowPtr) -1); |
if ( newDialogP == nil ) AlertUser(); |
SetPort(newDialogP); |
TextFont(kFontIDGeneva); |
TextSize(9); |
TextFace(normal); |
menuBar = GetNewMBar(rMenuBar); /* read menus into menu bar */ |
if ( menuBar == nil ) AlertUser(); |
SetMenuBar(menuBar); /* install menus */ |
DisposeHandle(menuBar); |
AppendResMenu(GetMenuHandle(mApple), 'DRVR'); /* add DA names to Apple menu */ |
DrawMenuBar(); |
gStopped = true; |
} /*Initialize*/ |
/* Check to see if a given trap is implemented. This is only used by the |
Initialize routine in this program, so we put it in the Initialize segment. |
The recommended approach to see if a trap is implemented is to see if |
the address of the trap routine is the same as the address of the |
Unimplemented trap. */ |
/* 1.02 - Needs to be called after call to SysEnvirons so that it can check |
if a ToolTrap is out of range of a pre-MacII ROM. */ |
Boolean TrapAvailable(short tNumber, TrapType tType) |
{ |
if ( ( tType == ToolTrap ) && |
( gMac.machineType > envMachUnknown ) && |
( gMac.machineType < envMacII ) ) { /* it's a 512KE, Plus, or SE */ |
tNumber = tNumber & 0x03FF; |
if ( tNumber > 0x01FF ) /* which means the tool traps */ |
tNumber = _Unimplemented; /* only go to 0x01FF */ |
} |
return NGetTrapAddress(tNumber, tType) != GetOSTrapAddress(_Unimplemented); |
} /*TrapAvailable*/ |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-07-22