A Magic Cap software package is a collection of objects organized to perform a specific set of user functions. Magic Cap provides several built-in packages, including the datebook, name card file, notebook and mail packages. More importantly, Magic Cap is a rich platform that provides a fertile environment to support packages. This guide describes CodeWarrior Magic/MPW, a software development environment for creating packages for Magic Cap.
In this guide, we will discuss the process of developing packages for Magic Cap. To use it effectively, you should be familiar with the C programming language and the principles of object-oriented programming.
Magic Cap software is distributed in packages that contain objects for performing tasks. Some packages are like conventional applications with specific purposes such as electronic mail and personal finance. Other packages perform tasks required by a variety of objects in Magic Cap. These include user-interface features like buttons and clocks.
While packages can vary according to purpose, they can also vary in
their structure. Some special purpose packages can contain code that
implements certain features, for example a inventory checker. Other
packages might not contain any code and will simply add objects to
Magic Cap. This second category can include data objects like stamps
and sounds but it can also include useful packages that benefit from
Magic Cap's rich set of user-interface tools. And of course plenty of
packages are in between these examples.
CodeWarrior Magic/MPW
CodeWarrior Magic/MPW is a software development environment for Magic Cap jointly developed by General Magic and Metrowerks. You create Magic Cap packages using an Apple® Macintosh® personal computer and CodeWarrior Magic/MPW.
CodeWarrior Magic/MPW provides a set of scripts and tools for building Magic Cap packages. These software development tools work under Macintosh Programmer's Workshop(TM) (MPW), a development environment supplied with CodeWarrior Magic/MPW. MPW includes a shell for editing text files and launching other tools, a scripting language, an object code debugger and many other features. CodeWarrior Magic/MPW also includes modified versions of the Metrowerks C/C++ compiler and linker.
Macintosh is the only development platform for Magic Cap packages right now, although development on other systems is possible in the future.
You will develop Magic Cap packages with standard MPW tools plus a few
special tools provided in CodeWarrior Magic/MPW. The next few
sections describe some of these special tools.
Magic Cap Simulator
While developing Magic Cap packages, you'll use a version of Magic Cap that runs on the Macintosh called Magic Cap Simulator that lets you create, edit and specify the behavior of live objects graphically. This allows you to see and use packages much as they will appear on personal communicators.
Magic Cap Simulator simulates a personal communicator and allows you to develop software without having to move your package to an actual communicator every time you make a change to your package, saving time in the development cycle.
Magic Cap Simulator is useful for two purposes. You can use it to run
and test packages with greater convenience than downloading the
package into a communicator. In addition, you can use it in the
software development process to modify objects and then dump them
back as ASCII text for ObjectMaker to use.
ObjectMaker
ObjectMaker is at the heart of CodeWarrior Magic/MPW. ObjectMaker is an MPW tool provided by General Magic as part of CodeWarrior Magic/MPW that translates text descriptions of Magic Cap objects into live representations of the objects. Magic Cap Simulator also has the ability to reverse this operation, converting live objects back to their text representations.
ObjectMaker processes two kinds of files, and each package includes at least one file of each kind (in addition to one or more source files that are processed by conventional compilers and assemblers). The first kind contains the descriptions of any classes defined by the package; this is called a class definition file. The second kind, called the instance definition file, contains descriptions of objects defined by the package.
See the chapter ObjectMaker for more
information on how to use ObjectMaker to develop Magic Cap packages.
Construction Tools
Typically, you'll start your package in CodeWarrior Magic/MPW, then build it and run it with the Macintosh development version of Magic Cap. In Magic Cap itself, you can use various tools and techniques to build your package. This process of adding to and changing your package in Magic Cap is called construction. In construction, you can create new viewable objects by dropping them from the Magic hat, then modify them with the move, copy, and stretch tools. You can also direct the behavior of objects in your package by writing scripts for them, as described in the next section.
See the section Construction Tools in the chapter on
Magic Cap Simulator for more information
on how
to use Magic Cap Simulator to modify objects for your packages.
Magic Script
Magic Cap includes a powerful scripting language called Magic Script. Magic Script provides a high-level way to arrange objects and connect them together. Only Magic Cap Simulator has the ability to create and edit Magic Script programs, but all versions of Magic Cap can execute Magic Script programs once they've been created.
When you create your own packages, you'll probably begin by writing programs in C using CodeWarrior Magic/MPW. You'll then leave CodeWarrior Magic/MPW and use Magic Cap itself to create, position, and connect the viewable objects you need. While running Magic Cap, you can use Magic Script to set up the interactions between these objects, such as buttons, switches, meters, text fields, and other user-interface elements. Your finished Magic Cap package will likely include code written in C as well as Magic Script components.
Magic Script is most useful in coordinating user-interactions with viewable objects like buttons. It is easier to write small scripts for these than to create the equivalent object subclasses. From a performance perspective, the two approaches are equivalent.
Many of the sample packages that come with CodeWarrior Magic/MPW
demonstrate Magic Script, especially HelloScripting and TicTacToe.
Other Tools in CodeWarrior Magic/MPW
In addition to ObjectMaker, CodeWarrior Magic/MPW includes a few other important development tools. These include the following:
This section describes how to build packages with CodeWarrior Magic/MPW. First we'll show you how to build a simple Magic Cap package named HelloWorld. This will give you a whirlwind tour of the CodeWarrior Magic/MPW development environment. From there we'll get more specific about the different components that go into CodeWarrior Magic/MPW and what they do.
CodeWarrior Magic/MPW contains several sample packages in addition to
HelloWorld, which we've already discussed. See the Samples folder in
CodeWarrior Magic/MPW to discover these packages. You can learn
something about them by looking at their source files and then
building and running them.
Building a Simple Package
Here's a list of steps for building a very simple Magic Cap package. We assume that CodeWarrior Magic/MPW has been successfully installed on your development system.
That's all there is to building a simple Magic Cap package. The black
box object in the package you've built does several things: you can
move, copy, or stretch it, and it plays a sound when you touch it.
Inside a Magic Cap Package
Let's take a look at the folder MyHelloWorld and examine its contents. You'll find four files:
The file Objects.Def contains a series of static object instance definitions that ObjectMaker uses to build the objects of a Magic Cap package.
Your package must include at least one instance definition file to be compiled by ObjectMaker. An instance definition file is a text file that consists of one or more object instance definitions.
Here's an example of an instance definition taken from Objects.Def in the MyHelloWorld folder:
Instance Greeter 'Hello World' 9; next: nilObject; previous: nilObject; superview: (Scene 'MyHelloWorld' 8); subview: nilObject; relativeOrigin: <0.0,-14.0>; contentSize: <90.0,90.0>; viewFlags: 0x7818D200; labelStyle: iBook12; color: -1; altColor: 0xFF000000; shadow: nilObject; sound: iSendSound; End Instance;
Each instance definition includes three parts:
A typical instance definition file will have a series of definitions organized hierarchically. The ObjectMaker chapter later in this book goes into greater detail about instance definition files and their syntax.
If your package includes any new classes, as most packages do, you must define them in a class definition file to be compiled by ObjectMaker. A class definition file is a text file that consists of one or more class definitions. Typically, a package's class definition file has the same name as the package, plus a .Def suffix.
Here's an example of a class definition taken from the class definition file from MyHelloWorld, followed by a discussion of its contents:
Define Class Greeter; inherits from Viewable; overrides Draw; End Class;
This class definition includes four parts:
End Class;
.
The ObjectMaker chapter later in this book goes into greater detail about class definition files and their syntax.
If your package includes any new classes, you must define the code that implements the methods of the new classes in C files. You can arrange your source code in any collection of files. MPW and CodeWarrior Magic/MPW require the .c suffix.
If a package has only one source file, it usually has the same name as the package plus a .c suffix. CodeWarrior Magic/MPW requires that your package have at least one .c file; if your package has no code, this file may just be an empty main function.
Following is an example of a C source file from MyHelloWorld:
#include "Magic.h" #include "Debug.h" #include "Package.h" main() { } #undef CURRENTCLASS #pragma segment Greeter #define CURRENTCLASS Greeter Method void Greeter_Draw(ObjectID self, ObjectID canvas, ObjectID clip) { Box ourContentBox; ulong color; color = PartColor(self, Hilited(self) ? partAltContent : partContent); ContentBox(self, &ourContentBox); FillBox(canvas, clip, &ourContentBox, color, pixelDither | pixelCopy); }
Although most of this file is written in standard C, you should notice these vitally important special elements:
#pragma segment Greeter
). This statement is required,
and the
segment name must match your class name exactly, including case. If
they don't match, ObjectMaker will fail. If you define more than one
class, make sure that you set the segment name correctly for each
method. You can have as many of these segment specifiers as you need,
switching from one segment to another before each method if
necessary.
#define
CURRENTCLASS Greeter
). This statement is required, and the
class name
must match your class name exactly, including case. If they don't
match, your package may fail. If you define more than one class, make
sure that you set the class name correctly for each method. You can
have as many of these class specifiers as you need, switching from
one class to another before each method if necessary.
C code written for Magic Cap classes is written in standard ANSI C. CodeWarrior Magic/MPW includes a few extra keywords to guide the development environment in this process.
Method | indicates that the function corresponds with an operation and supplies the implementation of the operation's interface. |
Intrinsic Method | corresponds to a simple intrinsic method. |
Intrinsic | specifies an operation with the intrinsic keyword set |
Private | used by callback routines |
Public | ... |
Note: the notion of public and private used by the keywords above refers to the issue of the scope of the functions they are associated with and not the issue of data hiding.
The Makefile contains MPW commands that build your package. You don't have to create or modify the Makefile; you can use the Create Build Commands item in the Magic menu to make one automatically. The Makefile usually has the same name as the package, plus the suffix .make.
Before you run the Create Build Commands script, you should set the current directory to the folder that contains your package's files. When you choose Create Build Commands, you'll have to specify the name of the new package and the source files that are used to build it. We'll go through this process when we build a sample package in the next section.
If you start your package by copying an existing package with the Clone Package command, you won't have to create a Makefile separately - you'll get one automatically when you clone.
For more information on the contents of a Makefile, see the MPW
Reference Manual.
Modifying an Object with Construction Tools
After you build and run your package with Magic Cap Simulator, you'll want to modify the package's appearance and store the results back into the package's source code. You'll do this with Magic Cap Simulator itself. Here's how to do it.
By dumping from Magic Cap Simulator and then importing dumped objects from CodeWarrior Magic/MPW, you can move back and forth between the two environments.
When using Magic Cap Simulator, you can do a lot more than just
modify existing objects. You can add new objects from the Magic hat.
Then, when you dump and import the dumped objects, the newly added
objects will be in your instance definition file. In addition, you
can create Magic Scripts for objects, specifying their behavior
without having to write C code. See the HelloScripting sample package
for more information.
Downloading a Package into a Communicator
Packages that you build and test with CodeWarrior Magic/MPW can be downloaded into a communicator. Here's how to do it:
That's all there is to downloading a Magic Cap package into a communicator. When you're finished with this process the communicator will restart and your package will be loaded.
If you don't have a Telebug box, you can download packages to your communicator using the cable supplied with Magic Xchange(TM) software (available separately) and DownloadPackage, supplied with CodeWarrior Magic/MPW. See the DownloadPackage files in the Cool Stuff folder for more information.
CodeWarrior Magic/MPW Menus
Find Menu
CodeWarrior Magic/MPW adds several items to the Find menu. All these
commands send their results to the MPW worksheet.
Search command | Description |
---|---|
Search Û Current Directory | Search all files in MPW's current directory for the selected text. |
Search Û Active Directory | Search all files in the directory that contains the front most window for the selected text. |
Search Û Target Directory | Search all files in the directory that contains the target window (the next-to-front most window) for the selected text. |
SearchClasses Û | Search all of CodeWarrior Magic/MPW's class definition files (the .Def files) for the selected text. |
SearchC Û | Search all the files in CodeWarrior Magic/MPW's Interfaces directory that end in .c or .h for the selected text. |
Search Û Indexicals.h | Search the Indexicals.h file for the selected text. |
Search Û Utilities.h | Search the Utilities.h file for the selected text. |
Search Û Samples | Search all the files in CodeWarrior Magic/MPW's Samples directory for the selected text. |
Search Û MagicDeveloper | Search all the files in the MagicDeveloper folder for the current text. |
These menu items are implemented in CodeWarrior Magic/MPW as scripts. You can search files in the MagicDeveloper folder directly by typing in the appropriate script name, as shown in the following table:
Function | Script Name |
---|---|
search .c, .h., and .Def files | SearchAll |
search .c and .h files | SearchC |
search .Def files | SearchClasses |
search all files | SearchMagic |
search files in Samples folder | SearchSamples |
CodeWarrior Magic/MPW creates a Directory menu that replaces the one supplied with MPW. Selecting an item from this menu sets MPW's current directory to that folder.
This Directory menu includes MagicDeveloper, MagicDevSystem (the folder containing Magic Cap and packages), MagicInterfaces (the folder with header and interface files for developing packages), and Magic Def files. Next, the Directory menu lists all the folders inside the Samples folder in MagicDeveloper.
The Directory menu also includes an item named Directory {Active}. If you select this item, the current directory will be set to the directory containing the frontmost window. This gives you a fast way to set the current directory to the package that you're working on.
The following table describes the items in the Magic menu. This table has three columns. The first two columns represent items in the Magic menu while the third column contains descriptions. The difference between the first two columns is that the first column represent CodeWarrior Magic/MPW commands while the second column represents options that control the behavior of these commands. When you select a menu item from the second column CodeWarrior Magic/MPW will display a check mark to indicate that the option is enabled.
Command | Option | Description |
---|---|---|
Build | This is the main CodeWarrior Magic/MPW command for building a Magic Cap package. | |
Resume Build | Resume Build provides a shortcut for continuing a failed build. Resume Build opens the Build Commands file in the current directory and continues executing MPW instructions from the point where the build failed. Resume Build is designed to save the time taken up by creating the Build Commands file if a correct one already exists. When in doubt, use Build. | |
debug build | If this item is checked, the package will be built with debugging code, such as calls to Log and Assert. If the item isn't checked, debugging code won't be compiled. | |
show progress | If this item is checked, progress information about the build will appear in the Worksheet window. | |
auto run | If this item is checked, Magic Cap will start and open the current package after a successful build. | |
Full Build | This command forces CodeWarrior Magic/MPW to rebuild an entire package. | |
Update Debugging Symbols | Update Debugging Symbols forces an update of the debugging information for the current package. Debugging symbols are usually automatically updated whenever a class definition file changes. | |
Macintosh Build Target | Check this item to build a copy of the package that works with Magic Cap Simulator. | |
Universal Device Build Target | Check this item to build a copy of the package that works on any Magic Cap communicator. | |
Other Build Targets... | Choose this item to select a specific vendor's device as a build target, such as Magic Link or Envoy. | |
Run Magic Cap | This item starts Magic Cap (if it isn't running already) without quitting MPW. If there's not enough memory to start Magic Cap without quitting MPW, you'll see an alert box instead. | |
Run Current Package | This item starts Magic Cap (if it isn't running already) without quitting MPW and runs the package in the current directory. The package isn't rebuilt, just run. If there's not enough memory to start Magic Cap without quitting MPW, you'll see an alert box instead. | |
autoDelete changes | If this item is checked, the Magic Cap changes file will be deleted when the package is built. | |
Set PC Card type | Use this item to determine the kind and size of PCMCIA card image if your build target is a communicator. | |
Download Current RAM Card | Use this item to try to download a memory card again without rebuilding the package. | |
to slot 1 | Check this item to set your download target to communicator slot 1. | |
to slot 2 | Check this item to set your download target to communicator slot 2. | |
Envoy Debugger Target | Use this item to build your package with debug symbols for Envoy. | |
Magic Link Debugger Target | Use this item to build your package with debug symbols for Magic Link. | |
Create Build Commands | Use this command to create a make file for your package automatically. When it displays a dialog asking for confirmation select Yes. | |
Clone Package | Create a new package based on the package in the current directory. This package will use names derived from the new packages name. |
Menu item | Description |
---|---|
Function Prototype | This command provides the C function prototype for a method. If there's nothing selected when you choose this command, Function Prototype will find the first word that precedes the insertion point and will assume that word is a method name. |
Open Utilities.h | Use this item as a quick way to open the Utilities.h file, which contains lots of important Magic Cap symbols. Exploring Utilities.h is a great way to learn more about Magic Cap. |
Open Indexicals.h | This item is a fast way to open the Indexicals.h file, which contains the symbolic names for all Magic Cap indexicals. You can find out a lot about Magic Cap by rooting through this file. |
Open Objects.Def | This item quickly opens the current package's Objects.Def file. |
Bowser Pro | Choose this item to start Bowser Pro, the famous class browser. |
Echo Log | This item copies the contents of Magic Cap Simulator's log file to the MPW worksheet in MagicDeveloper:SystemSoftware:Log. |
Clear Log | This item clears the contents of Magic Cap's log file. |
Convert Dumped Indexicals | Use this command to help identify objects in your package; that can be replaced by references to indexicals. Before using this command, run Magic Cap and choose the Find Indexicals command from the Debug menu. This will put a list of indexical candidates into the log file. After creating the list of indexical candidates, return to MPW and choose this item. CodeWarrior Magic/MPW will change your Objects.Def file to incorporate the suggested changes. The conversion is automatic; you just have to confirm that you want the changes saved. |
Import Dumped Objects | Use this item if you've dumped your package's objects with the "Dump Package" item in Magic Cap's Examine menu. This item reads the text from the Log file and places it into a new Objects.Def file. Import Dump Objects also preserves your previous Objects.Def by saving it in a folder named Old inside the package's folder. |
Find Instance | When you've selected a line that contains a reference to an object in an Objects.Def file, use this item to find the instance definition of the object referred to. |
Get Unique Instance ID | You can use this item to generate an instance ID that's unique within the instance's Objects.Def file. After you select this item, the unique ID will appear at the insertion point. |
Convert ObjectIDs to Instance IDs | This command scans the active window for ObjectIDs of the form $hhhhhhhh and converts them into instance IDs of the form ddd. You should use this command after you use Magic Cap Simulator's Dump Inspector Target menu, then paste the newly dumped objects into your Objects.Def file. |
Convert {Indexicals} to iNames | This command converts indexical references, like this: {60,12}, into readable identifiers, like this: iBook10Bold. It works on the active window. |
Run Telebug | This command starts Telebug, sparing you from having to remember how to spell Telebug and type it. |
Set Source Break | This command sets a Telebug breakpoint. Put the insertion point into a line in your package's C source file, then choose this item to set a breakpoint before that line. |
You can use the Function Prototype item in the Utils menu while you're programming in MPW. The Function Prototype command quickly looks up the return value and parameters for any method.
To use this command, select the name of the function, method or operation that you want to learn about, or place the insertion point in or after the function, method or operation. Choose Function Prototype from the Utils menu.
Magic Cap Simulator includes a menu named Discipline that can help you make sure your package's objects are consistent. The most useful item in this menu is the Validate Package item. You can use this to check the view hierarchy in your package, which is a source of common problems with package development.
CodeWarrior Magic/MPW comes with a special version of Magic Cap that can be used for making screen shots for documentation. The standard version of Magic Cap Simulator accurately simulates the 2-bit graphics model used in communicators. Magic Cap for screen shots actually uses the same depth as your Macintosh graphics display to give more graphical information for screen shots and avoid unpleasant dithering artifacts.
This section describes some of the common problems that you may encounter when you're trying to build and run packages.
This usually indicates that your Magic Cap Changes file is corrupt. To fix the problem, throw away the Magic Cap Changes file. You'll lose changes you've made, but Magic Cap should return to normal.
When you start Magic Cap, you may repeatedly enter the debugger and see messages like this:
User break at xxxxxxxx HiBoot+0092 User break at xxxxxxxx HiBoot+0176 User break at xxxxxxxx MacTCP_Install+007E User break at xxxxxxxx MacUtilities_InstallMacClusterFile+0140
Congratulations! You've discovered the insidious double-secret Magic debugging mode, which is triggered by running with the Macintosh caps lock key down. Simply release the caps lock key and you won't be bothered like this again.
If you try to build your package and get messages from MPW about files not being found, you may have failed to set the directory correctly. Be sure you use the Set Directory item in MPW's Directory menu to set the directory to the one that contains your source files before you choose the Create Build Commands menu item.
You should run MPW Shell with a memory partition of at least 7500K when developing packages. In the Finder, select Get Info from the File menu, then type 7500 into the Suggested Size and Minimum Size boxes (or the Current Size box if you're not running System 7.1 or later).
Due to a bug in ObjectMaker, if the last line of a file is a comment that starts with // , the first line of the next file processed will be treated like a comment.
Code Warrior Magic normally updates the class symbol information used by the debugger whenever you change a class definition file in your package. However, if you switch to work on another package but don't happen to change a class definition file in the new package, the debugger won't update its symbols. Instead, it will show the class names for the package you were working on before. To point the debugger at the symbols for your new package, choose the Update Debugging Symbols menu item.
The advanced information in this section may be useful to you as you become more adept at developing packages with CodeWarrior Magic/MPW.
#pragma segment
statement before each class definition,
as General Magic has always required, each class is in a separate
segment. So if one private routine of one class calls the private
routine of another, the linker will generate an A5 relative jump that
will fail miserably in Magic Cap.
You no longer need to put #pragma segment in front of each class. Removing the #pragma segments will reduce the likelihood of a serious crash if you do call a private routine of one class from another class.
Load, Install, and Reset are called every time the device powers up or is reset. You should therefore be careful what you do in these methods. Structure your code so that initialization that should be done only once is actually done only once.
Write private routines passed to operations like Each and RunSoon assuming that they will be executed outside of the context of their package. A private routine that uses intrinsics, indexicals, or class numbers will fail in unpredictable and horrible ways if it's executed outside its package context.
Private routines can cause many subtle bugs. Use them only when you need to. Magic Cap itself uses methods and intrinsics 2/3 of the time and private routines only 1/3.
Reducing the number of private routines you use can reduce the amount of code you need to include in a patch. Since private routines can't be easily patched, to replace a single private routine you might need to include new versions of many methods.
There is no way to allocate a pointer to a buffer that will persist past a power cycle. This means that it is dangerous to store such pointers in persistent objects.
Don't put the object IDs of transient objects into the fields of persistent objects, and vice versa. In the first case, these fields will be set to nilObject after a power cycle, which might pose problems for your class. In the second case, the persistent objects will become a memory leak after a power cycle, since the enclosing object will have disappeared without being explicitly destroyed.
copy = CopyNear(original, enclosingObject);If you use these methods, transient objects will stick with transient objects and persistent with persistent.
responder = CopyNear(responder, nearThis);
Calling MoveNear like this will ensure that all objects enclosed in the responder are copied near the nearThis parameter, if necessary.
This error often appears when you're using StringToText to create a text object. Unfortunately, the text object created is transient. You shouldn't use it as a parameter to a call to SetSubject. Instead, use StringToTextNear to create text objects.
This rule has a minor exception: you can use HasObject to check if an operation you've just called has deleted an object. HasObject is safe when you know that the object ID was good very recently.
This is a basic C programming rule, but it can be hard to remember. Don't pass a pointer to a local variable when it will be kept past the lifetime of the function containing the declaration of that variable. In Magic Cap, this bug seems to pop up most in completion routines for timers.
If you use BeginRead or BeginModify or ReadFields or WriteFields, be careful to call MakeUsable and MakeStorable when needed.
You'll run into this problem when you use ReadFields to read from one object and WriteFields to put the data into another object. You must call MakeUsable and MakeStorable between the ReadFields and WriteFields, in code that looks like this:
ReadFields(self, &MyClassFields); itemToChange = MakeUsable(self, MyClassFields.foo); /* do some work here */ OtherClassFields.bar = MakeStorable(other, itemToChange); WriteFields(other, &OtherClassFields);If you don't, you'll have a subtle bug that won't show up unless your users are brave enough to try filing.
Use this sample as a model for your citations:
Instance OctetString 100; data: 'Hello World'; End Instance; Instance OctetString 101; data: $ 0000 0000; End Instance; Instance Telename 102; authority: (OctetString 100); identity: (OctetString 101); End Instance; Instance Identifier 'HelloWorld' 103; End Instance; Instance Citation 104; title: (Identifier 'HelloWorld' 103); author: (Telename 102); majorEdition: 1; minorEdition: nilObject; End Instance;
Garbage collection doesn't happen very often in Magic Cap, so you can't rely on it to clean up obsolete objects for you. For example, Magic Cap won't garbage collect to make room for a memory allocation. If there's a lot of junk occupying memory, your allocations might fail. Allocations that fail cause big problems for Magic Cap.
Also watch out for situations where many objects point to one no-copy object, or to an object that isn't owned by anybody in particular.
When you do use this option you'll need to modify your code wherever you use function pointers. CodeWarrior Magic/MPW has a #pragma statement for forcing the compiler to use near addressing mode. For example,
#pragma push #pragma near_code Method void Foo() { Each(xxx, (EachFunction)ForEachElemDo, xxx); } #pragma popIn practice this can lead to two problems. First, code in large packages may need to be rearranged to insure that the 32K offset is not exceeded. In the example above this means that the EachFunction must be near the code that calls Each and that any private functions referenced are also nearby.
Second, moving the #pragmas inside the function to surround just the individual statement does not work. You must use the #pragmas around the entire function.