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.
TESampleInit.c
/*------------------------------------------------------------------------------ |
# |
# Apple Macintosh Developer Technical Support |
# |
# MultiFinder-Aware Simple TextEdit Sample Application |
# |
# TESample |
# |
# This file: TESampleInit.c - C Source (Init Segment) |
# |
# Copyright © 1989 Apple Computer, Inc. |
# All rights reserved. |
# |
# Versions: |
# 1.00 08/88 |
# 1.01 11/88 |
# 1.02 04/89 |
# 1.03 06/89 |
# 1.04 06/92 |
# |
# Components: |
# TESample.p June 1, 1989 |
# TESample.c June 1, 1989 |
# TESampleInit.c June 4, 1992 |
# TESampleGlue.a June 1, 1989 |
# TESample.r June 1, 1989 |
# TESample.h June 1, 1989 |
# PTESample.make June 1, 1989 |
# CTESample.make June 1, 1989 |
# TCTESample.¹ June 4, 1992 |
# TCTESample.¹.rsrc June 4, 1992 |
# TCTESampleGlue.c June 4, 1992 |
# |
# TESample 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. The fundamental TextEdit |
# toolbox calls and TextEdit autoscroll are demonstrated. It |
# also shows how to create and maintain scrollbar controls. |
# |
# 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 Sample before |
# beginning a new application. Sample is a simple app. which doesnÕt |
# use TextEdit or the Control Manager. |
# |
------------------------------------------------------------------------------*/ |
/* Segmentation strategy: |
This program consists of three segments. |
1. "Main" contains most of the code, including the MPW libraries, and the |
main program. This segment is in the file Sample.c |
2. "Initialize" contains code that is only used once, during startup, and |
can be unloaded after the program starts. This segment is in the file |
SampleInit.c. |
3. "%A5Init" is automatically created by the Linker to initialize globals |
for the MPW libraries and is unloaded right away. */ |
/* 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. */ |
/* Clipboard strategy: |
This program does not maintain a private scrap. Whenever a cut, copy, or paste |
occurs, we import/export from the public scrap to TextEdit's scrap right away, |
using the TEToScrap and TEFromScrap routines. If we did use a private scrap, |
the import/export would be in the activate/deactivate event and suspend/resume |
event routines. */ |
/* A/UX is case sensitive, so use correct case for include file names */ |
#include <Limits.h> |
#include <types.h> |
#include <quickdraw.h> |
#include <fonts.h> |
#include <events.h> |
#include <controls.h> |
#include <windows.h> |
#include <menus.h> |
#include <textedit.h> |
#include <dialogs.h> |
#include <desk.h> |
#include <scrap.h> |
#include <toolutils.h> |
#include <memory.h> |
#include <segload.h> |
#include <files.h> |
#include <osutils.h> |
#ifndef AUX |
# include <diskinit.h> |
#endif |
#include <packages.h> |
#include "TESample.h" /* bring in all the #defines for TESample */ |
#include <traps.h> |
/* A/UX C understands neither #pragma, nor segments, so don't pragma */ |
#ifndef AUX |
#pragma segment Initialize |
#endif |
/* 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. It is |
global information, anyway. */ |
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 */ |
/* GNumDocuments is used to keep track of how many open documents there are |
at any time. It is maintained by the routines that open and close documents. */ |
extern short gNumDocuments; /* maintained by Initialize, DoNew, and DoCloseWindow */ |
/* Set up the whole world, including global variables, Toolbox managers, |
menus, and a single blank document. */ |
/* 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; |
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) BigBadError(eWrongMachine); |
/* 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, |
ApplicationZone, 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) BigBadError(eSmallSize); |
/* 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(); */ |
#ifndef AUX |
PurgeSpace(&total, &contig); |
if (total < kMinSpace) |
if (UnloadScrap() != noErr) |
BigBadError(eNoMemory); |
else { |
PurgeSpace(&total, &contig); |
if (total < kMinSpace) |
BigBadError(eNoMemory); |
} |
#endif |
/* 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. */ |
menuBar = GetNewMBar(rMenuBar); /* read menus into menu bar */ |
if ( menuBar == nil ) |
BigBadError(eNoMemory); |
SetMenuBar(menuBar); /* install menus */ |
DisposeHandle(menuBar); |
AppendResMenu(GetMenuHandle(mApple), 'DRVR'); /* add DA names to Apple menu */ |
DrawMenuBar(); |
gNumDocuments = 0; |
/* do other initialization here */ |
DoNew(); /* create a single empty document */ |
} /*Initialize*/ |
/* Used whenever a, like, fully fatal error happens */ |
void BigBadError(short error) |
{ |
AlertUser(error); |
ExitToShell(); |
} |
/* 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 == (unsigned char) 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) != NGetTrapAddress(_Unimplemented, ToolTrap); |
} /*TrapAvailable*/ |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14