mirror of
https://github.com/IanDarwin/OpenLookCDROM.git
synced 2026-01-23 19:16:53 +00:00
2196 lines
90 KiB
Plaintext
2196 lines
90 KiB
Plaintext
From: d88-jwa@mumrik.nada.kth.se (Jon Wätte)
|
|
Newsgroups: comp.sys.mac.programmer.misc,comp.sys.mac.programmer.info,comp.answers,news.answers
|
|
Subject: The Mac Programming FAQ Answer sheet. [READ ME!]
|
|
Date: 15 May 1995 03:46:53 GMT
|
|
Approved: news-answers-request@MIT.Edu
|
|
Expires: 23 May 1995 00:00:00 GMT
|
|
Message-ID: <3p6ird$h5k@news.kth.se>
|
|
|
|
Archive-name: macintosh/programming-faq
|
|
|
|
Mac Programming Frequently Asked Questions Answer Sheet
|
|
Last update: 10 May 95 - sharp dressed FAQ
|
|
|
|
Please download a copy of this answer sheet and search it before you
|
|
post to the 'net, to help reduce bandwidth.
|
|
|
|
Please send all correspondence regarding content directly to the current
|
|
caretaker and content editor, Chris Thomas, <thunderone@delphi.com>.
|
|
All submissions sent will be considered to be in the public domain
|
|
unless stated otherwise (in which case they will not be included in this
|
|
FAQ sheet). When writing, be sure that you include something
|
|
appropriate in the subject line. I'm now automatically deleting mail
|
|
with blank or whitespace subjects unread due to the growing nasty
|
|
practice of sending junk email without a subject. The idea, apparently,
|
|
is to be cute and get you to read the mail without deleting it. This
|
|
sheet was started and is distributed by Jon Watte, whom you may reach as
|
|
<h+@austin.metrowerks.com>.
|
|
|
|
This sheet is currently archived on nada.kth.se where you can reach it
|
|
using afs as /afs/nada.kth.se/public/ftp/pub/hacks/mac-faq/CSMP_PD_FAQ
|
|
or using anonymous FTP as pub/hacks/mac-faq/CSMP_PD_FAQ You can also
|
|
find it on rtfm.mit.edu unedr the name macintosh/programming-faq. WWW
|
|
version is available as <http://www.nada.kth.se/~d88-jwa/mac-faq.html>.
|
|
|
|
No FAQ can substitute for real documentation (some of which is
|
|
mentioned in this FAQ) If you ask a question in comp.sys.mac.programmer
|
|
which has a good answer in one of the important sources, you will probably
|
|
not get an answer. (Inside Macintosh, Macintosh Technical Notes being
|
|
important sources).
|
|
|
|
There is NO or VERY LIMITED error checking in the code examples, FOR
|
|
BREVITY ONLY. You should make sure you ALWAYS check ALL return codes,
|
|
and handle any that you are not prepared to deal with appropriately.
|
|
Needless to say, do not use the code as is.
|
|
|
|
Exciting new stuff: More general dev tools update. See especially
|
|
question 1.2. List Manager replacements. The usual tweaking.
|
|
|
|
Topics:
|
|
[search for *number* to find a topic quickly]
|
|
[topics changed since last FAQ are marked with "+", new topics with ">"]
|
|
|
|
1. +Development Tools
|
|
getting started, tool-specific issues
|
|
2. Memory
|
|
handles, large arrays, resource handles
|
|
3. User Interfacing
|
|
menus, windows, events, multitasking
|
|
4. Files
|
|
Mac fopen, wdrefnums, getting full pathnames
|
|
5. Imaging
|
|
QuickDraw and the means to avoid it
|
|
6. Text
|
|
Text editing packages, string conversion
|
|
7. Communications and Networking
|
|
Serial ports, TCP/IP, sockets
|
|
8. Interapplication Communication
|
|
AppleEvents, OSA, Scripting, and You
|
|
9. Dynamic Linking & Code Resources
|
|
the dynamics of code resources & trap patches
|
|
10. Compatibility
|
|
gestalt & glue
|
|
11. Optional System Software
|
|
11.1. QuickTime
|
|
codec details and the lack thereof
|
|
12. Third-Party Solutions
|
|
12.1. Databases
|
|
client/server solutions for the masses
|
|
12.2. >Circumventing Toolbox Limitations
|
|
foul baggage begone- List Manager replacements
|
|
13. Dessert
|
|
yummies the Macintosh Way
|
|
14. Contributors
|
|
whodunnit
|
|
|
|
*1* Development and debugging tools for the Macintosh
|
|
|
|
1.1) Q: What do I need to start writing Macintosh software?
|
|
|
|
A: A Mac, a lot of time, and a few hundred $. Although you can develop
|
|
software on a Classic-type machine, it is not to be attempted by the
|
|
weak of heart or stressed of time. If you're doing paid work and/or
|
|
work for a company, a Quadra-class machine is a must; remember that your
|
|
time costs your employer much more than just your salary. A PowerMac is
|
|
highly preferable. 16 MB is a minimum to run at all comfortably (40 MB
|
|
recommended), and Virtual Memory (including RamDoubler, unfortunately)
|
|
is not suited for development work. Similarly, if you don't have at
|
|
least 80 MB free on your hard disk you need to buy more space. You will
|
|
also need a CD-ROM drive.
|
|
|
|
You need a development system such as CodeWarrior, MPW Pro, Symantec C++
|
|
8.0 or Prograph, you need at least some of the New Inside Mac books
|
|
(Toolbox Essentials, Files, Memory come to mind) and a good entry-level
|
|
third-party book may help.
|
|
|
|
Once you are up to speed on the general layout of the Mac and its
|
|
toolboxes, you should call APDA and order the monthly developer mailing,
|
|
which will give you a CD chock full of documentation, utilities and
|
|
system software once a month. You will also, obviously, need a CD
|
|
player; Apple's own CD600 is a very good buy at the time of this
|
|
writing. If you don't have the dough for the monthly mailing
|
|
($250/year) you can order a _develop_ subscription; this quarterly
|
|
magazine ($30-$50/year) comes with a CD containing most Inside Mac
|
|
documentation. Another good product to order is the MacOS SDK, which
|
|
for $99 gives you a CD with every API in existence up to and including
|
|
the 7.5 Mac Toolbox additions. It's somewhat redundant if you already
|
|
have the Developer CD subscription. <apda@appplelink.apple.com> Apple's
|
|
Developer Web has almost all of the contents of the Developer CD online.
|
|
<http://www.info.apple.com/dev>
|
|
|
|
If you don't know how to program, go learn your language of choice
|
|
BEFORE attempting a "real" Mac application. Programming is a discipline
|
|
often requiring different thought processes than your normal day job. A
|
|
beginning book, like Lippman: The C++ Primer, one of the Teach Yourself
|
|
C++ books, or the primers available on the CodeWarrior CD, might help.
|
|
|
|
An indispensable Mac programming tool is the Macintosh Programmer's
|
|
Toolbox Reference (MPTA), an up-to-date hypertext reference guide
|
|
containing reference material on the New Inside Mac-documented portions
|
|
of the Toolbox with lightning-fast look-up and mostly correct usage
|
|
hints and code snippets. MPTA can be found on the Developer CD, and is
|
|
also offered on a seperate $99 CD. <apda@applelink.apple.com>
|
|
|
|
Think Reference version 2.0.1, precursor to MPTA, contains reference
|
|
material on many parts of the Mac toolbox with lightning-fast look-up
|
|
and mostly correct usage hints and code snippets. While it does not
|
|
cover any post-System 7 system additions, nor the modern "universal"
|
|
headers format, it does include information on the standard C/C++
|
|
libraries. Available wherever fine Symantec products are sold -
|
|
<apda@applelink.apple.com> for one.
|
|
|
|
1.2) Q: What is the most used Macintosh development system?
|
|
|
|
A: Currently, the three most widely used are CodeWarrior (CW), MPW, and
|
|
Symantec C++, probably in that order, though I don't have any
|
|
statistics. The latest version of any one of these is adequate for Mac
|
|
development.
|
|
|
|
CodeWarrior: In early 1994, CodeWarrior came out of nowhere and grabbed
|
|
a large share of the market visibility because they had the fastest
|
|
compiler and they generated PowerPC code as well as 68K code. Today,
|
|
CodeWarrior has the smoothest development environment and most complete
|
|
C++ implementation, supporting both templates and exceptions. CW/6
|
|
includes C, C++, and Object Pascal support, and can generate x86
|
|
binaries. Among hobbyists, CW seems to be the most popular because of
|
|
it's low price, ultra-fast compile time, and support that no other
|
|
company on the planet can match. See comp.sys.mac.programmer.codewarrior
|
|
for more information and CodeWarrior-related praise. Contact
|
|
<sales@metrowerks.com>.
|
|
|
|
MPW: The grandaddy of all Mac development environments, descended from
|
|
the original Mac development environment based on a Lisa. MPW is an
|
|
extremely flexible, powerful, Unix-like command line environment with
|
|
makefile, multiple windows and split-pane support. Many development
|
|
tools are MPW-based. MPW Pro comes with C, C++, Pascal, assemblers for
|
|
both 68k and PowerMac, various other useful tools, and the C++-based
|
|
framework MacApp for a reasonable price. MPW has in the past been
|
|
extremely slow, but shows signs of redemption. Contact
|
|
<apda@applelink.apple.com>.
|
|
|
|
Symantec C++: This is the eighth-generation descendant of the C
|
|
environment favored by Mac developers for over five years. Symantec C++
|
|
8.0 is a complete, scriptable, modular development environment including
|
|
C, C++, and soon, a PowerPC assembler. The C++ implementation supports
|
|
templates. A development version of a PowerPC C++ compiler supporting
|
|
exceptions and RTTI is available at Symantec's devtools site. SC++ 8.0
|
|
doesn't at this time support 68k Mac development. For that purpose,
|
|
you're required to use the old, decrepit TPM development environment,
|
|
which is included. Contact <sales@devtools.symantec.com>.
|
|
|
|
There are also at least two Fortran compilers, at least three SmallTalk
|
|
implementations (ObjectWorks, SmallTalk/V and SmallTalkAgents) and
|
|
others. There are ways of stripping SmallTalk apps so they're smaller
|
|
and faster as standalone apps than in the environment.
|
|
|
|
Languge Systems has Object Pascal and Fortran for PowerMac. Absoft has
|
|
Fortran and C++ for PowerMac. These all require MPW.
|
|
|
|
There's also a world-class LISP/CLOS implementation from Apple called
|
|
Macintosh Common Lisp. Recently, Apple announced that DigiTool has
|
|
licensed MCL with the intent (among other things) to provide a PowerMac
|
|
version and other updates.
|
|
|
|
Zedcor has FutureBasic, which seems to be a very popular... It also
|
|
seems to be the only well-supported implementation of BASIC on
|
|
Macintosh.
|
|
|
|
CSI has MacForth, of which I only know the name and someone who says
|
|
it's pretty good.
|
|
|
|
There is another good Common Lisp implementation: Procyon Common Lisp.
|
|
I don't know if it is actively supported, but Procyon CL is also
|
|
available for DOS, OS/2 and Windows (as Allegro CL/PC) and actively
|
|
developed.
|
|
|
|
A new possible up-and-coming languge is Apple's Dylan, which is
|
|
something of a cross between BASIC, Pascal, and C. C-based code can be
|
|
used directly from Dylan, but Dylan can't yet be used directly from C.
|
|
The Apple Dylan environment is rumored to be as far beyond MPW as MPW is
|
|
beyond thick bundles of FORTRAN punch cards.
|
|
|
|
1.3) Q: Okay, which is the most used Mac programming languge?
|
|
|
|
A: The existing Macintosh code base is mostly C, with C++ second, and
|
|
Pascal finding it's niche in third. Few people are writing mainstream
|
|
software in Pascal anymore, probably because (a) it's rather hard to
|
|
move to non-Mac platforms (b) Pascal is only rarely being taught past
|
|
the first year in Computer Science.
|
|
|
|
1.4) Q: Where do I find a free/share/copyleftware C compiler for the Mac?
|
|
Is there a GCC for the mac? What about the FSF boycott of Apple products?
|
|
|
|
A: There is no really good solution for a "for-free" C development
|
|
system for the Mac. GCC has been ported, but requires the MPW shell and
|
|
MPW assembler to run; these have to be bought from APDA. There is a
|
|
standalone port of GCC 1.37 on nic.switch.ch:software/mac/src/think_c.
|
|
|
|
gcc-1.37r14 V1.1 standalone is available for ftp at nic.switch.ch:
|
|
software/mac/src/think_c.
|
|
|
|
A not-entirely-stable port of GCC 2.3.3 to MPW is available for ftp at
|
|
atg.apple.com [anyone know the directory?]. A much more solid port of
|
|
GCC 1.37 is available for MPW as well.
|
|
|
|
Stan Shebs <shebs@cygnus.com>, the driving force behind all of the MPW
|
|
GCC ports, is working on a new port of GCC 2.5.8.
|
|
|
|
For those whose main interest is in developing only text-based C/C++
|
|
programs, using GCC under MacMiNT might be appropriate. MacMiNT is a
|
|
UNIX like operating system ported from the Atari ST which supports many
|
|
freely available UNIX utilities like GCC, GDB, make, tcsh, byacc, perl,
|
|
and more. MacMiNT stuff can be found at nic.switch.ch in
|
|
'software/mac/src/macmint'.
|
|
|
|
The FSF/LPF boycott of Apple products is over as of January 1995, which
|
|
means they will now incorporate changes made for Macintosh into their
|
|
main code base, if such changes are easily incorporated, and they
|
|
won't be any more antagonistic to Mac programmers than they would be
|
|
to any other micro-to-workstation-class programmers.
|
|
|
|
So what are you waiting for? Go out and port something from GNU! Send in
|
|
the changes! We still lack decent free development tools!
|
|
|
|
1.5) Q: Are there any other free Mac development platforms?
|
|
|
|
A: The best source for information on free compilers/interpreters is the
|
|
Free Compilers FAQ which is written by Brian Connors
|
|
<connorbd@cleo.bc.edu>. Watch for it in c.s.m.p.info.
|
|
|
|
1.6) Q: What's the difference between the MPW, Think and CodeWarrior
|
|
environments?
|
|
|
|
A: As of CodeWarrior/6, MPW 3.3, and Symantec C++ 8.0.1 (SC++),
|
|
CodeWarrior will allow faster turnaround times, MPW will provide the
|
|
most flexibility and overall power, and Symantec C++ has the edge with
|
|
regard to helpful project browsing features.
|
|
|
|
CW C++ supports templates and exceptions, Symantec C++ supports only
|
|
templates, MPW's new compilers are based on Symantec C++.
|
|
|
|
SC++ 8 doesn't generate 68k code, while pre-CW/6 CodeWarrior requires
|
|
you to use seperate (virtually identical) environments, and builds are
|
|
controlled from a Makefile in MPW, of course.
|
|
|
|
All three need much hard disk space. SC++ requires the most RAM. MPW
|
|
requires the most disk space.
|
|
|
|
MPW is the slowest, followed distantly by SC++, which is followed
|
|
closely by CodeWarrior.
|
|
|
|
The best thing about MPW is that you can write scripts and make files to
|
|
do anything you want in the way you want it. SC++ and CodeWarrior can
|
|
be AppleScripted to do builds that require more than one link operation,
|
|
but the process is more involved, and CW doesn't currently support
|
|
scripting in full. SC++ 8 can do builds which require more than one
|
|
link operation.
|
|
|
|
For the MPW and CodeWarrior environments, there are four source level
|
|
debuggers; Metrowerks, SADE, SourceBug, Voodoo Monkey. The latter is an
|
|
experimental debugger with support for threads debugging; the middle is
|
|
bundled with MPW while SADE has to be bought separately (but is fully
|
|
scriptable in its own scripting language). Metrowerks Debugger is
|
|
included with CodeWarrior.
|
|
|
|
The Think environments have their own integrated debuggers; the Think
|
|
Pascal one has a lot of useful features while the Think C/C++ one is a
|
|
little more basic (but is gaining in functionality with each release).
|
|
|
|
Metrowerks has their own debugger which works like the MPW debuggers; i e
|
|
it runs the application standalone and pokes at it from the outside,
|
|
while the Think debuggers run the application "wrapped" in a special
|
|
environment, making for some subtle interferences with your heap (which
|
|
you usually don't notice). The Metrowerks Debugger is Thread
|
|
Manager-savvy on the 68k side.
|
|
|
|
BOTTOM LINE:
|
|
|
|
If you're developing for both Power and regular 68k Macs, you need
|
|
CodeWarrior. MPW is an option which makes sense if you need to develop
|
|
code for non-CFM OpenTransport or if you have a ridiculously large
|
|
number of independent code modules to compile, or if you're a Unix
|
|
person. CodeWarrior, in addition to it's own integrated environment,
|
|
includes the non-compiler parts of MPW and MPW-hosted Metrowerks
|
|
compilers/linkers. SC++ is an option only for PowerMac development.
|
|
|
|
1.7) Q: What is a good low-level debugger for the Mac?
|
|
|
|
A: MacsBug is freely available for ftp from <ftp://ftp.apple.com>; log
|
|
in as user anonymous and give your FULL e-mail address as password.
|
|
MacsBug is your basic monitor-type debugger that takes a few hundred Ks
|
|
of memory, and lets you break, step, disassemble, look at the stack etc
|
|
of most anything running on your Mac. Since it's free (it's also on the
|
|
developer CDs) and provides most of the functionality you need, this is
|
|
a popular choice. As of 6.5d10, Macsbug supports PowerPC debugging.
|
|
|
|
Jasik Designs has a debugger called The Debugger which can do both low-
|
|
and high-level debugging, with or without source and for all types of
|
|
code, application, code resources, everything. This is the debugger of
|
|
choice for many large developers because of its high power and many
|
|
features not found anywhere else. However; newcomers beware! This is
|
|
the Lamborghini of debuggers; if you know how to drive it, it is the
|
|
fastest way from A to B; if you don't, you'll just end up in the ditch.
|
|
The Debugger is PowerMac native and supports PowerPC disassembly. It
|
|
includes an excellent code coverage tool and MacNosy, a general
|
|
disassembler. Support is direct from the author and generally great.
|
|
<macnosy@jasik.com>
|
|
|
|
1.8) Q: Are there any visual developments environments for the
|
|
Mac (comparable to Visual C++)?
|
|
|
|
A: There is no Visual C++ as such. However, there is a C++ parser/editor
|
|
called ObjectMaster which provides good browsing and editing capabilities
|
|
if you already have a C++ compiler. A demo is available on the CodeWarrior
|
|
CD. Think C++ comes with a browser built-in, and you can edit
|
|
dialogs/windows using plain old ResEdit, even for your custom view types.
|
|
|
|
Symantec C++ 7.0 also bundles a view editor/code generator called Visual
|
|
Architect; it is fairly complete and has a good level of integration
|
|
into the Think Project Manager.
|
|
|
|
AppMaker is a GUI builder/code generator. Granted, it's not as nice as
|
|
VC++, but it's quite a product in any case.
|
|
|
|
MarksMan version 3.0 has totally revised TCL templates, and now
|
|
generates well-thought-out TCL code. It can also generate ANSI C code
|
|
etc.
|
|
|
|
Also, Neuron Data has their UI tool called Open Interface, which is
|
|
better than VC++ and creates code portable across 35 platforms.
|
|
Unfortunately it's $2500 per developer per platform. There's also two
|
|
other cross-platform products called XVT and Galaxy, the former has
|
|
gotten flak on UseNet while the latter reportedly is the premier
|
|
cross-platform application builder framework; with everything from
|
|
styled text to network support.
|
|
|
|
There is a fully visual, dynamic, object oriented data-flow-driven
|
|
programming language for the Mac called Prograph CPX. It features a
|
|
full-featured class library, a powerful, user-extensible GUI Builder, full
|
|
access to the entire Mac toolbox, a database engine, high-level interfaces
|
|
to SQL, Oracle, etc. But the coolest thing about Prograph is its
|
|
interpretative debugger, fully integrated with the visual code editor,
|
|
which lets you write your code _while it's running_. Execution
|
|
automatically rolls back to where changes you make have relevance. A
|
|
PowerMac-native compiler and a Windows version are expected in '95. A
|
|
complete demo version is available from <sales@prograph.com>. Cost is
|
|
$695 ($395 for students).
|
|
|
|
SmalltalkAgents comes with a GUI builder, which lets you draw your
|
|
interface, and then outputs the code for you.
|
|
|
|
If you'd rather do Common Lisp, Macintosh Common Lisp offers a Common
|
|
Lisp Object System with support for most Mac interface items; you can
|
|
edit code while it is running and build stand-alone applications.
|
|
|
|
However, all of these tools generate rather larger binaries with larger
|
|
system demands than a program written in C. On the other hand; C++
|
|
programs require more memory and disk space than programs written in
|
|
assembly. It's a trade-off, and I believe this type of tools is the
|
|
wave of the near future.
|
|
|
|
1.9) Q: What class libraries are there for the Mac?
|
|
|
|
A: Apart from the libraries mentioned above, there are three contenders:
|
|
MacApp, TCL, and PowerPlant. "Bedrock" will never be released as a
|
|
product, although parts of it surface in TCL 2.0 and other parts will be
|
|
the base for the OpenDoc Parts Framework.
|
|
|
|
MacApp is a heavy-duty class library that has tons of features and a
|
|
steep learning curve; it runs under MPW with Pascal or C++, and also
|
|
under Think Pascal 4.0 A major application written in MacApp is
|
|
PhotoShop.
|
|
|
|
TCL stands for Think Class Library and comes with Think Pascal, C or
|
|
C++. It is a smaller library that still fills most peoples needs; since
|
|
Think C implements a subset of C++ (the most important OO concepts such
|
|
as virtual functions and inheritance) and the TCL is carefully written
|
|
not to take advantage of any C++ features not in Think C, you can use it
|
|
with Think C. A major application written in TCL is Lotus 1-2-3. (TCL
|
|
1.1.3) Starting with Symantec C++ 7.0, Think Class Library 2.0 using
|
|
templates and "real" C++ objects is shipping.
|
|
|
|
The C++ Standard Template Library (STL) compiles under Symantec C++
|
|
and CodeWarrior, and versions are available for both.
|
|
|
|
PowerPlant is the Metrowerks CodeWarrior offering; it's written by the
|
|
guy who designed the Think Class Library, but it has a lot of
|
|
differences from the original TCL; for one, it's not a monolithic one
|
|
base class framework. On the other hand, it has some catching up to do
|
|
before it reaches the level of MacApp. It is gaining quite fast on TCL,
|
|
but isn't all there yet. It has the most complete support for
|
|
AppleEvents & scripting & drag & drop other modern features.
|
|
|
|
1.10) Q: How should I debug and test my software?
|
|
|
|
A: Get ahold of, and install, the extensions DoubleTrouble,
|
|
DisposeResource and EvenBetterBusError. They will catch 80% of any
|
|
memory related bugs you may have, including many bugs that follow NULL
|
|
handles or pointers. (Jasik's Debugger (see above) obviates the need
|
|
for these.)
|
|
|
|
A low-level debugger is required, and while you install it, install the
|
|
"leaks" dcmd which will help you catch memory leaks in your application.
|
|
All of these tools are available from <ftp.apple.com>.
|
|
|
|
1.11) Q: Are there any good Mac programming magazines?
|
|
|
|
A: One Mac programming magazine I know of is MacTech Magazine (formerly
|
|
MacTutor). It covers a variety of Mac programming topics on various
|
|
levels. Operating independently from Apple, it has a lot of stuff for
|
|
the beginning Mac programmer, as well as occasional nuggets for the more
|
|
experienced of us. <custservice@xplain.com>
|
|
|
|
Another VERY GOOD Magazine is _develop_ which is put out by Apple four
|
|
times a year; it comes with a CD containing code for all articles ever
|
|
published in _develop_, and a lot of documentation and system software
|
|
freebies as well. $30/year in the US. <dev.subs@applelink.apple.com>
|
|
|
|
1.12) Q: What about protected memory? I'm sick and tired of re-booting
|
|
when my application crashes.
|
|
|
|
A: Write better software!
|
|
|
|
Or install The Debugger from Jasik Designs, which can provide your
|
|
application with write-protection of critical parts of memory, if you have
|
|
a 68030-equipped Mac.
|
|
|
|
Making the Mac OS memory-protected is tricky, because applications expect
|
|
to be able to write to low memory, the system heap, temporary memory,
|
|
window lists, and even each other's heaps in some interapplication
|
|
communication solutions that date back to before AppleEvents and the PPC
|
|
Toolbox. To add to the burden, Apple's own software tends to be the
|
|
worst offender in these cases.
|
|
|
|
But fear not, Mac fans! Jonathan Kimmitt has written Patmos, the
|
|
"Protected address translation mode operating system". It is an
|
|
application that brings the advantages of protected mode programs to
|
|
your Quadra class Macintosh by the simple expedient of taking over the
|
|
memory management unit of the 68040 in a very simple kernel (<100K in
|
|
size), we immediately gain compatibility with the BSD unix program
|
|
environment. The advantages of this are as follows:
|
|
|
|
(a) You can run certain programs (such as /bin/sh) designed for MacBSD
|
|
(b) You can compile almost all GNU software including C and C++ without.
|
|
modifying the source code in any way
|
|
(c) All programs run with a flat 32-meg address space, with no worries
|
|
about 32K segments or the other mac paraphernalia.
|
|
(d) The majority of program bugs can be caught cleanly without crashing
|
|
your mac
|
|
(e) All your files are shared between Patmos and MacOS so you can edit
|
|
using your favourite mac editor, then immediately compile in Patmos
|
|
without having to reboot or copy files around.
|
|
|
|
The downside is that not all macs use the memory management unit in the
|
|
same way, or even have the same kind of MMU, so Patmos may not run on
|
|
your particular mac model. However, since the kernel source code is
|
|
very small, the task of adapting it to a new environment is very simple,
|
|
and once achieved, all application programs running in user mode are
|
|
enabled to run without even recompiling.
|
|
|
|
<ftp://nic.switch.ch in /software/mac/src/patmos>
|
|
|
|
1.13) Q: I have this library written in (Think) Pascal that I want to use
|
|
from Think C/Symantec C, but I get link errors/don't know how to do it.
|
|
What should I do?
|
|
|
|
A: Start by writing a .h file describing the interface. Remember to
|
|
declare the Pascal functions "pascal". Build a library with Think Pascal
|
|
and convert it with oConv.
|
|
|
|
Do you get link errors on symbols defined in your Pascal lib? Check the
|
|
capitalisation used.
|
|
|
|
Do you get errors on symbols like LMUL and LDIV? Those functions are
|
|
defined in the Think Pascal library Runtime.lib or uRuntime.lib. Include
|
|
uRuntime.lib and try again.
|
|
|
|
Do you get link errors on standard symbols like thePort? This is due to
|
|
bad capitalization in Symantec's libs. Run oConv with .v checked. This
|
|
will create a TEXT file with a .v extension. Open that with a text
|
|
editor and correct the capitalization. Run oConv again, with .v checked
|
|
this time too.
|
|
|
|
Do you still get errors on standard symbols? Are you using Think
|
|
C/Symantec C++ version 6 or higher? Then you must open the library (after
|
|
converting it) from Think C version 5, and remove the unit named
|
|
%_TOOLBOX. (If I'm not mistaken, this is the toolbox init unit, which
|
|
you won't need anyway.)
|
|
|
|
1.14) Q: CodeWarrior vs. Think/Symantec C++: Which is better?
|
|
|
|
A: See the above discussion on CodeWarrior, Think, and MPW for a full
|
|
understanding of the issues involved.
|
|
|
|
1.15) Q: Can CodeWarrior read Think libraries?
|
|
|
|
A: Yes, in a way. Here are the steps required.
|
|
|
|
1) Secure a copy of Think Pascal and a machine that can run it
|
|
2) Import the Think C library into Think Pascal
|
|
3) Build a Think Pascal library (in MPW format)
|
|
4) Import MPW format library into CodeWarrior
|
|
|
|
1.16) Q: What are some good books on the subject of learning the Mac
|
|
Toolbox?
|
|
|
|
A: Any of Dan Parks Sydow's numerous books on the subject. Recommended
|
|
also is Dave Mark's _Ultimate Mac Programming_ (a Macworld book, for
|
|
some odd reason). Stay away from Dave Mark's _Learn C on the Mac_ and
|
|
_Learn C++ on the Mac_.
|
|
|
|
See also Nick DeMello's books review, posted in c.s.m.p.info from time
|
|
to time.
|
|
|
|
1.17) Q: Source code! I want source code! Where can I find some?
|
|
|
|
A: Celestin Company, Inc. sells the Apprentice 2 CD-ROM. Apprentice
|
|
contains over 600 megabytes of programmer utilities and up-to-date
|
|
source code in CodeWarrior, Symantec, and MPW projects for C, C++, and
|
|
Pascal. <ftp://ftp.teleport.com/vendors/cci/apprentice/apprentice.hqx>
|
|
for an index and info. <celestin@olympus.net>
|
|
|
|
Also, the alt.sources.mac archive at <ftp://ftpbio.bgsu.edu> contains a
|
|
lot of misc. source code and snippets not found elsewhere.
|
|
|
|
<ftp://nic.switch.ch> is another good source for unique source code.
|
|
|
|
Info-mac is a good source for source, info-mac/dev/src.
|
|
|
|
1.18) Q: I'm trying to use a largish array in Think C, but get a "code
|
|
overflow" error. This is valid C, why doesn't it work?
|
|
|
|
A: The ANSI standard does not guarantee that any structure larger than
|
|
32767 bytes be correctly handled. Because of historical constraints,
|
|
the Mac memory model is built around several small blocks of size 32K or
|
|
less; these are used both for code and global/static data. If you want
|
|
to use more code or data, you have to turn on "far code" or "far data" -
|
|
you still will not get around the restriction of 32K code or data per
|
|
compiled file, though.
|
|
|
|
This is one area where CodeWarrior's 68k support shines; it works around
|
|
most such limitations and it doesn't cost much in performance either!
|
|
|
|
As opposed to, say, DOS or Windows, however, you can allocate as much
|
|
memory as you want (and there is in the machine) and step through it
|
|
using ordinary pointers; it's just that global and static data space is
|
|
addressed off the A5 register using a 16bit displacement addressing mode
|
|
in the 68000 processor.
|
|
|
|
On the PowerPC, everything is 32bit from the start; that runtime model
|
|
is much more like UNIX. The horizon is the limit.
|
|
|
|
*2* Memory
|
|
|
|
2.1) Q: What is a handle?
|
|
|
|
A: A handle is a pointer to a pointer to something. However, it is more
|
|
than that; creating a handle by taking the address of one of your own
|
|
pointers does NOT create a Handle; the Memory Manager will only deal
|
|
properly with Handles that are created using NewHandle or something that
|
|
calls it (such as NewRgn or GetResource).
|
|
|
|
2.2) Q: When do I have to lock a Handle?
|
|
|
|
A: The contents of a Handle may move, and when it does, the pointer your
|
|
handle is pointing to is changed to point to the new address so your
|
|
handle is always valid. The toolbox may call the memory manager to
|
|
allocate more memory pretty much anytime you call it (the toolbox) and
|
|
when memory is allocated, your handle may move in memory. Don't
|
|
dereference a handle into a pointer (or take the address of a field in a
|
|
record a handle is double-pointing to) and then call the toolbox and
|
|
expect the pointer to still be valid. The only way to ensure that the
|
|
pointer will still be valid is to call HLock on the handle to lock it.
|
|
|
|
Use HGetState and HSetState to save & restore the "locked" state of a
|
|
handle when you lock it.
|
|
|
|
2.3) Q: How do I dispose of Handles?
|
|
|
|
A: DisposeHandle (formerly called DisposHandle) once and ONLY once will
|
|
do the trick. Trying to dispose of an already disposed Handle is an
|
|
error. DoubleTrouble (see above) will catch such bugs when they do
|
|
occur.
|
|
|
|
2.4) Q: What about resources?
|
|
|
|
A: Calling GetResource returns NULL if the resource is not found or
|
|
there is not enough memory, else it returns a handle to the resource.
|
|
This handle may be moved or locked like any other handle, but DO NOT
|
|
call DisposeHandle to get rid of a resource handle - call
|
|
ReleaseResource. DisposeResource (see above) will catch this kind of
|
|
bug.
|
|
|
|
Remember that AddResource makes a resource handle out of an ordinary
|
|
handle, and RemoveResource or DetachResource makes an ordinary handle
|
|
out of a resource handle. You cannot call AddResource with a resource
|
|
handle; you have to DetachResource it first.
|
|
|
|
Resource handles are automagically disposed when the resource file they
|
|
belong to is closed.
|
|
|
|
*3* User / Machine interaction
|
|
|
|
3.1) Q: How do I read the modifier keys of the keyboard?
|
|
|
|
A: Just call EventAvail and check the event.modifiers field.
|
|
Only works when you are in the foreground. You can also use
|
|
GetKeys(), or (as a last resort) check the lo-mem global KeyMap
|
|
directly.
|
|
|
|
3.2) Q: How do I move the mouse cursor to a specific position?
|
|
|
|
A: Wait! Don't do it! There has to be a better way!
|
|
|
|
If you feel you HAVE to do it (for a game or VERY special simulation
|
|
situation) you can use the Cursor Device Manager documented in the tech
|
|
notes on <ftp.apple.com>. If that manager is not installed, as it's not
|
|
on older Macs, you can use the following code:
|
|
|
|
You need to have some low-memory globals defined. they may be defined
|
|
in SysEqu.h.
|
|
|
|
#define MTemp 0x828
|
|
#define RawMouse 0x82c
|
|
#define CrsrNewCouple 0x8ce
|
|
|
|
Note that CrsrNewCouple is actually a combination of two globals, just
|
|
to make our life slightly easier.
|
|
|
|
The code I use to move the mouse is:
|
|
|
|
*code*
|
|
void
|
|
MoveMouseTo ( Point where ) {
|
|
|
|
HideCursor ( ) ;
|
|
* ( Point * ) RawMouse = where ;
|
|
* ( Point * ) MTemp = where ;
|
|
* ( short * ) CrsrNewCouple = -1 ;
|
|
ShowCursor ( ) ;
|
|
}
|
|
*end*
|
|
|
|
You need to hit a couple more global variables if you want this to work
|
|
properly in a multiple-monitor system, but i forget what they are
|
|
offhand. poke through SysEqu.h, and you should be able to figure it out
|
|
without a problem.
|
|
|
|
On the PowerPC, these lo-mem globals may not be available for native
|
|
applications; however, all Power Macintoshes implement the Cursor Device
|
|
Manager. All Macs made after March '93 (including Centris 650 and 610)
|
|
implement the Cursor Device Manager, in fact.
|
|
|
|
There is also a file on nada.kth.se:pub/hacks/mac-faq/MoveMouse.c which
|
|
shows how to use the Cursor Device Manager, written by an excellent
|
|
Apple engineer. Grab!
|
|
|
|
Careful, version 1.0 of the Universal Header "CursorDevices.h" file was
|
|
completely incorrect. Use 2.0a3 or later.
|
|
|
|
3.3) Q: My menus don't show up in the menu bar
|
|
|
|
A: If your menus are hiearchical, you'll have to install them manually;
|
|
GetNewMBar won't do it for you. See also 3.5.
|
|
|
|
3.4) Q: When the user selects my menus, I get strange results back; they
|
|
seem to have different menu IDs than my menus?
|
|
|
|
A: The Menu ID as used by the menu manager is NOT the same thing as the
|
|
MENU resource ID (used in the MBAR resource and with GetMenu()) When you
|
|
create a MENU, ResEdit sets the menu ID to the MENU resource ID, but if
|
|
you re-number the resource, you will have to open the menu in ResEdit
|
|
and change the menu ID using the "Edit MENU ID" menu item.
|
|
|
|
3.5) Q: I use GetMenu() to find a menu in the menu bar, and then change
|
|
it, but it seems I have a memory leak OR my changes don't "punch
|
|
through"
|
|
|
|
A: GetMenu() is only intended if you don't already have the menu "in
|
|
memory." The call you should use almost all the time is GetMHandle()
|
|
which gets the handle to a menu in the current menu bar by its menu ID
|
|
(not resource id).
|
|
|
|
3.6) Q: What about pre-emptive multitasking?
|
|
|
|
A: To the user, the Mac multitasking method, which builds upon each
|
|
application calling WaitNextEvent, GetNextEvent or EventAvail every so
|
|
often and the Process Manager/MultiFinder switching applications only at
|
|
such calls, is at least as good as preemtive multitasking, because the
|
|
present system priotitizes user interface responsiveness over everything
|
|
else. The only shortfall about this is formatting floppies, which locks
|
|
up the Mac CPU. This is because the Mac floppy controller is really
|
|
stupid, and would happen even if the Mac multitasked preemptively.
|
|
|
|
There IS "real" pre-emptive multitasking available for use in Mac
|
|
applications; the expensive way is buying A/UX 3.0 which can have Mac
|
|
applications written as UNIX processes; the cheap way is installing the
|
|
Thread Manager which will allow you to create pre-emptive threads.
|
|
However, the restrictions on those threads are the same as those on Time
|
|
Manager tasks: don't call any function in an unloaded segment, and don't
|
|
call QuickDraw or any toolbox call which may move memory (which are most
|
|
ToolBox calls; paradoxally, BlockMove is safe :-) as are, surprisingly,
|
|
FSRead and FSWrite). The latest word from Apple is that this
|
|
preemptive support is going away, to be replaced by something else in
|
|
Copland.
|
|
|
|
There are several problems with making the Mac OS preemptive; including
|
|
apps that draw outside their windows or directly to screen, user
|
|
dragging and other issues. The system is being reimplemented for 8.0
|
|
(Copland) to solve these problems.
|
|
|
|
*4* Files
|
|
|
|
4.1) Q: How do I tell fopen() to open a file the user has selected using
|
|
StandardGetFile?
|
|
|
|
A: The "standard" ANSI C file functions are less than well suited for
|
|
the Macintosh way of doing things. However, if you are doing a port for
|
|
your own enjoyment and benefit (or maybe for in-house work) you can use
|
|
the following function: (see below about converting a wdRefNum into a
|
|
vRefNum/parID pair)
|
|
|
|
*code*
|
|
FILE *
|
|
fopen_mac ( short vRefNum , long parID , char * fileName , char * mode ) {
|
|
|
|
short oldVol ;
|
|
short aVol ;
|
|
long aDir , aProc ;
|
|
FILE * ret = NULL ;
|
|
|
|
if ( GetVol ( NULL , & oldVol ) ) {
|
|
return NULL ;
|
|
}
|
|
if ( GetWDInfo ( oldVol , & aVol , & aDir , & aProc ) ) {
|
|
return NULL ;
|
|
}
|
|
if ( HSetVol ( NULL , vRefNum , parID ) ) {
|
|
return NULL ;
|
|
}
|
|
ret = fopen ( fileName , mode ) ;
|
|
if ( HSetVol ( NULL, aVol , aDir ) ) {
|
|
/* an error we can't currently handle */
|
|
}
|
|
if ( SetVol ( NULL, oldVol ) ) {
|
|
/* an error we can't currently handle */
|
|
}
|
|
return ret ;
|
|
}
|
|
*end*
|
|
|
|
All of the above is necessary for one reason or another - if you are
|
|
interested, by all means look HSetVol up in Think Reference 2.0 or New
|
|
Inside Mac: Files.
|
|
|
|
In older versions of MPW; this wouldn't work since the MPW libraries
|
|
used to do a GetVol and explicitly use that value by itself.
|
|
|
|
4.2) Q: When can I use the HOpen, HCreate etc file calls? Are they only
|
|
System 7 calls?
|
|
|
|
A: All the HXxx calls that take a vRefNum and parID as well as the file
|
|
name are implemented in glue that works on any system that has HFS
|
|
(meaning 3.2 and up with the HD20 INIT, and all systems from System 6
|
|
and up)
|
|
|
|
The glue is available in MPW 3.2 and up, and Think C 5.0 and up. This
|
|
goes for all HXxx calls except HOpenDF; therefore, if you are interested
|
|
in System 6 compatibility, use HOpen instead and make sure you don't
|
|
allow file names beginning with a period.
|
|
|
|
4.3) Q: Why do you say wdRefNum sometimes and vRefNum sometimes?
|
|
Why do you say parID sometimes and dirID sometimes?
|
|
|
|
A: When the Mac first made an appearance in 1984, it identified files by
|
|
using a vRefNum (volume reference number meaning a floppy disk or later
|
|
hard disk) and a name. Once HFS saw the light of day, folders within
|
|
folders became a reality, and you needed a dirID as well to point out
|
|
what folder you really meant on the volume. However, older programs
|
|
that weren't being rewritten still knew nothing about directory IDs, so
|
|
Apple had SFGetFile make up "fake" vRefNums that didn't just specify a
|
|
volume, but also a parent folder. These are called wdRefNums (for
|
|
working directory) and were a necessary evil invented in 1985. You
|
|
should not create (or, indeed, use) wdRefNums yourself.
|
|
|
|
There is a system-wide table that maps wdRefNums onto vRefNum/parID
|
|
pairs. There is a limit to the size of this table. A dirID and a parID
|
|
is almost the same thing; you say "parID" when you mean the folder
|
|
something is in, while you say a "dirID" when you mean the folder
|
|
itself. If you for instance have a folder called "Foo" with a folder
|
|
called "Bar" in it, the parID for "Bar" would be the dirID for "Foo."
|
|
|
|
4.4) Q: How do I convert a wdRefNum as returned by SFGetFile
|
|
into a vRefNum/parID pair to use with the HXxx calls?
|
|
|
|
A: Use GetWDInfo, which is declared as:
|
|
|
|
Pascal OSErr GetWDInfo ( short wdRefNum , short * vRefNum , long * parID
|
|
, OSType * procID ) ;
|
|
|
|
The procID parameter must be non-NULL and point to an OSType variable,
|
|
but the value of that variable can and should be ignored.
|
|
|
|
It is recommended that, as soon as you get your hands on a wdRefNum, for
|
|
instance from SFGetFile, you directly convert it into a vRefNum/parID
|
|
pair and always use the latter to reference the folder.
|
|
|
|
4.5) Q: How do I select a folder using SFGetFile?
|
|
|
|
A: This requires a custom dialog with a filter proc. It is too
|
|
complicated to show here, but not totally impossible to comprehend.
|
|
There is sample code on ftp.apple.com, in the directory dts/snippets, on
|
|
how to do this.
|
|
|
|
4.6) Q: How do I get the full path of a file referenced by a vRefNum,
|
|
parID and name?
|
|
|
|
A: You don't.
|
|
|
|
OK, I cheated you. There is exactly ONE valid reason to get the full
|
|
path of a file (or folder, for that matter) and that is to display its
|
|
location to the user in, say, a settings dialog. To actually save the
|
|
location of the file you should do this: (assuming the file is in an
|
|
FSSpec called theFile - you can use FSSpecs in your program even if you
|
|
don't run under System 7; just make your own MyFSMakeFSSpec that fills
|
|
in the FSSpec manually if it's not implemented)
|
|
|
|
*code*
|
|
if ( ! aliasManagerAvailable ) { /* System 6 ? */
|
|
GetVolumeName ( theFile -> vRefNum , vName ) ;
|
|
GetVolumeModDate ( vRefNum , & date ) ;
|
|
Save ( vName , date , parID , fileName ) ;
|
|
} else {
|
|
NewAlias ( NULL , theFile , & theAlias ) ;
|
|
Save ( theAlias ) ;
|
|
DisposeHandle ( ( Handle ) theAlias ) ;
|
|
}
|
|
*end*
|
|
|
|
If you are really concerned about these issues (of course you are!) you
|
|
should save BOTH of these methods when available, and load back whatever
|
|
is there that you can handle; since users may be using your application
|
|
in a mixed System 6/System 7 environment.
|
|
|
|
To get back to the file is left as an exercise for the reader.
|
|
|
|
To open a file using fopen() or the Pascal equivalent, see above about
|
|
using and not using HSetVol.
|
|
|
|
4.7) Q: What about actually getting the full path for a file? I promise
|
|
I will only use it to show the location of a file to the user!
|
|
|
|
A: Enter PBGetCatInfo, the Vegimatic of the Mac file system. Any Mac
|
|
hacker of knowledge has taken this system call to his heart. Note that
|
|
this sample code isn't all there, but should point you in the right
|
|
direction:
|
|
|
|
*code*
|
|
Boolean IsFolder(FSSpec *fs) // this function is called later
|
|
{
|
|
CInfoPBRec rec;
|
|
|
|
rec.hFileInfo.ioNamePtr = fs -> name;
|
|
rec.hFileInfo.ioVRefNum = fs -> vRefNum;
|
|
rec.hFileInfo.ioDirID = fs -> parID;
|
|
|
|
|
|
if ( !fs -> name [ 0 ] )
|
|
{
|
|
rec . hFileInfo . ioFDirIndex = 0 ;
|
|
} else
|
|
{
|
|
rec . hFileInfo . ioFDirIndex = -1 ;
|
|
}
|
|
|
|
rec . hFileInfo . ioFVersNum = 0 ;
|
|
PBGetCatInfoSync (&rec);
|
|
|
|
return(!rec.hFileInfo.ioFlAttrib & 0x10);
|
|
}
|
|
*end*
|
|
|
|
*code*
|
|
OSErr GetFolderParent(FSSpec *fss, FSSpec *parent)
|
|
{
|
|
CInfoPBRec rec;
|
|
short err;
|
|
|
|
*parent = *fss;
|
|
rec.hFileInfo.ioNamePtr = parent -> name ;
|
|
rec.hFileInfo.ioVRefNum = parent -> vRefNum ;
|
|
rec.hFileInfo.ioDirID = parent -> parID ;
|
|
|
|
if ( !parent -> name [ 0 ] ) // dougw -- neg of FAQ
|
|
{
|
|
rec . hFileInfo . ioFDirIndex = 0 ;
|
|
}
|
|
else
|
|
{
|
|
rec . hFileInfo . ioFDirIndex = -1 ;
|
|
}
|
|
|
|
rec . hFileInfo . ioFVersNum = 0 ;
|
|
err = PBGetCatInfoSync ( & rec ) ;
|
|
|
|
if ( ! ( rec . hFileInfo . ioFlAttrib & 0x10 ) ) { /* Not a folder */
|
|
if ( ! err ) {
|
|
err = dirNFErr ;
|
|
}
|
|
} else {
|
|
parent -> parID = rec . dirInfo . ioDrParID ;
|
|
BlockMove(rec.dirInfo.ioNamePtr, parent->name, rec.dirInfo.ioNamePtr[0]);
|
|
}
|
|
return err ;
|
|
}
|
|
*end*
|
|
|
|
*code*
|
|
OSErr GetFullPathHandle ( FSSpec * fss , Handle * h )
|
|
{
|
|
Handle tempH = NULL;
|
|
FSSpec fs = * fss ;
|
|
FSSpec sSpec;
|
|
|
|
if(*h == NULL) // allocate a handle if needed
|
|
{
|
|
*h = NewHandle(0);
|
|
}
|
|
|
|
while ( fs . parID > 1 )
|
|
{
|
|
tempH = NULL ;
|
|
PtrToHand ( & fs . name [ 1 ] , & tempH , fs . name [ 0 ] ) ;
|
|
PtrAndHand ( ( void * ) ":" , tempH , 1 ) ;
|
|
HandAndHand ( * h , tempH ) ;
|
|
SetHandleSize ( * h , 0L ) ;
|
|
HandAndHand ( tempH , * h ) ;
|
|
DisposeHandle ( tempH ) ;
|
|
|
|
tempH = NULL ;
|
|
GetFolderParent ( & fs , & sSpec ) ;
|
|
fs = sSpec ;
|
|
}
|
|
|
|
// fs should now contain info about the volume itself
|
|
PtrToHand ( & fs . name [ 1 ] , & tempH , fs . name [ 0 ] ) ;
|
|
PtrAndHand ( ( void * ) ":" , tempH , 1 ) ;
|
|
HandAndHand ( * h , tempH ) ;
|
|
SetHandleSize ( * h , 0L ) ;
|
|
HandAndHand ( tempH , * h ) ;
|
|
DisposeHandle ( tempH ) ;
|
|
tempH = NULL ;
|
|
|
|
if (!IsFolder ( fss ) )
|
|
{
|
|
SetHandleSize ( * h , GetHandleSize ( * h ) - 1 ) ;
|
|
}
|
|
|
|
DisposeHandle(tempH);
|
|
return 0 ;
|
|
}
|
|
*end*
|
|
|
|
4.8) Q: So how do I get the names of the files in a directory?
|
|
|
|
A: You use PBGetCatInfo again, but this time you set ioFDirIndex to 1 or
|
|
more (you need to know the dirID and vRefNum of the folder you're
|
|
interested in) You then call PBGetCatInfoSync for values of ioFDirIndex
|
|
from 1 and up, until you get an fnfErr. Any other err means you are not
|
|
allowed to get info about THAT item, but you may be for the next. Then
|
|
collect the names in the string you made ioNamePtr point to as you go
|
|
along. Note that you need to fill in the ioDirID field for each
|
|
iteration through the loop, and preferably clear the ioFVersNum as well.
|
|
|
|
Note that the contents of a directory may very well change while you are
|
|
iterating over it; this is most likely on a file server that more than
|
|
one user uses, or under System 7 where you run Personal File Share.
|
|
|
|
4.9) Q: How do I find the name of a folder for which I only know the
|
|
dirID and vRefNum?
|
|
|
|
A: You call (surprise!) PBGetCatInfo! Make ioNamePtr point to an empty
|
|
string (but NOT NULL) of length 63 (like, an Str63) and ioFDirIndex
|
|
negative (-1 is a given winner) - this makes PBGetCatInfo return
|
|
information about the vRefNum/dirID folder instead of the file/folder
|
|
specified by vRefNum, parID and name.
|
|
|
|
4.10) Q: How do I make the Finder see a new file that I created? Or if I
|
|
changed the type of it; how do I display a new icon for it?
|
|
|
|
A: You call (surprise!) PBGetCatInfo followed by PBSetCatInfo for the
|
|
FOLDER the file is in. Inbetween, you should set ioDrMdDat to the
|
|
current date&time. Code:
|
|
|
|
*code*
|
|
OSErr
|
|
TouchFolder ( short vRefNum , long parID ) {
|
|
|
|
CInfoPBRec rec ;
|
|
Str63 name ;
|
|
short err ;
|
|
|
|
rec . hFileInfo . ioNamePtr = name ;
|
|
name [ 0 ] = 0 ;
|
|
rec . hFileInfo . ioVRefNum = vRefNum ;
|
|
rec . hFileInfo . ioDirID = parID ;
|
|
rec . hFileInfo . ioFDirIndex = -1 ;
|
|
rec . hFileInfo . ioFVersNum = 0 ;
|
|
err = PBGetCatInfoSync ( & rec ) ;
|
|
if ( err ) {
|
|
return err ;
|
|
}
|
|
GetDateTime ( & rec . dirInfo . ioDrMdDat ) ;
|
|
rec . hFileInfo . ioVRefNum = vRefNum ;
|
|
rec . hFileInfo . ioDirID = parID ;
|
|
rec . hFileInfo . ioFDirIndex = -1 ;
|
|
rec . hFileInfo . ioFVersNum = 0 ;
|
|
rec . hFileInfo . ioNamePtr [ 0 ] = 0 ;
|
|
err = PBSetCatInfoSync ( & rec ) ;
|
|
return err ;
|
|
}
|
|
*end*
|
|
|
|
4.11) Q: Aren't we done with PBGetCatInfo soon?
|
|
|
|
A: Well, it turns out that you can also find out whether an FSSpec is a
|
|
file or a folder by calling PBGetCatInfo and check bit 4 (0x10) of
|
|
ioFlAttr to see whether it is a folder. You may prefer to call
|
|
ResolveAliasFile for this instead.
|
|
You can also check the script of the file's title using PBGetCatInfo and
|
|
check the ioFlFndrXInfo field if you want to work with other script
|
|
systems than the Roman system.
|
|
|
|
Another common use is to find out how many items are in a folder; the
|
|
modification date of something or the correct capitalization of its name
|
|
(since the Mac file system is case independent BUT preserves the case
|
|
the user uses)
|
|
|
|
4.12) Q: How do I set what folder should initially be shown in the
|
|
SFGetFile boxes?
|
|
|
|
A: You stuff the dirID you want to show into the lo-mem global
|
|
CurDirStore, and the NEGATIVE of the vRefNum you want into the lo-mem
|
|
global SFSaveDisk.
|
|
|
|
If you are using CustomGetFile and return sfSelectionChanged from an
|
|
"init" message handler, you must remember to clear the script code, else
|
|
the selection will not change.
|
|
|
|
4.13) Q: How do I find the folder my application started from? How do I
|
|
find the application file that's running?
|
|
|
|
A: Under System 7, you call GetProcessInformation using the
|
|
ProcessSerialNumber kCurrentProcess with a pointer to an existing FSSpec
|
|
in the parameter block. This will give you your file, and, by using the
|
|
vRefNum and parID, the folder the application is in.
|
|
|
|
*code*
|
|
OSErr CurrentProcessLocation(FSSpec *applicationSpec)
|
|
{
|
|
ProcessSerialNumber currentPSN;
|
|
ProcessInfoRec info;
|
|
|
|
currentPSN.highLongOfPSN = 0;
|
|
currentPSN.lowLongOfPSN = kCurrentProcess;
|
|
info.processInfoLength = sizeof(ProcessInfoRec);
|
|
info.processName = NULL;
|
|
info.processAppSpec = applicationSpec;
|
|
return ( GetProcessInformation(¤tPSN, &info) );
|
|
}
|
|
*end*
|
|
|
|
Beware from writing to your applications resource or data forks; the
|
|
former breaks on CDs/write protected floppies/file servers/virus
|
|
checkers, the latter fails on PowerPC as well as in the above cases.
|
|
|
|
4.14) Q: When can I use those nifty, easy to use FSSpec calls?
|
|
|
|
A: In Systems >= 7, in System 6 with QuickTime installed, in any system
|
|
if you use the FSpCompat functions provided by MoreFiles [see below].
|
|
|
|
4.15) Q: I hate dealing with the low-level file manager stuff; why
|
|
didn't Apple provide a complete high-level interface using FSSpecs?
|
|
|
|
A: Good question. Apple, in the guise of Jim Luther of Mac Developer
|
|
Technical Support, has written a library called MoreFiles, which not
|
|
only provides a high-level interface to low-level file stuff, but
|
|
provides FSSpec glue for Systems below 7. MoreFiles is available on the
|
|
Developer CD's (see above) and also at Appple's developer ftp site.
|
|
|
|
*5* Imaging with QuickDraw
|
|
|
|
5.1) Q: Why is CopyBits so slow?
|
|
|
|
A: It is not. It just requires some hand-holding to get good results.
|
|
The main rules are: Make sure the source and destination pixMaps are of
|
|
the same depth.
|
|
|
|
Make sure the front color is black and the back color is white.
|
|
|
|
Use srcCopy and don't use a masking region, unless it's rectangular.
|
|
|
|
Copy to an unclipped window (the frontmost window). Make sure the
|
|
ctSeed values of the source pixMap and dest pixMap match.
|
|
|
|
Copying few and large pixMaps is faster than copying many and small
|
|
ones. Icon-sized sprites count as small ones.
|
|
|
|
Make sure your source bitmap or pixelMap has the same alignment, when
|
|
adjusted for the source and destination rect expressed in global screen
|
|
coordinates. The necessary alignment is 32 bits (4 bytes), although 128
|
|
bit (16 byte) alignment is probably even better on 68040 macs and won't
|
|
hurt on other macs.
|
|
|
|
Example of global alignment:
|
|
|
|
Your window is positioned at (42,100) (H,V)
|
|
|
|
Your destination rectangle is (10,20)-(74,52)
|
|
|
|
The alignment coefficient of the rectangle in global coordinates is
|
|
(42+10)*bitDepth where bitDepth is one of 1,2,4,8,16 or 32.
|
|
|
|
Make sure your source pixmap rect has the same coeffecient modulo your
|
|
alignment factor (in bits) For black&white macs, this is still true,
|
|
although bitDepth is fix at 1. Offscreen pixMaps can calculate with a
|
|
"global posistion" of 0,0 and get correct results.
|
|
|
|
5.2) Q: Why is CopyBits still too slow?
|
|
|
|
A: Because there is always some overhead involved in calling QuickDraw;
|
|
you have the trap dispatcher, clipping checks, and checking whether the
|
|
CopyBits call is being recorded in a PICT handle (if you called
|
|
OpenPicture)
|
|
|
|
If you can't live with this, look at 4.8 below, but PLEASE try and make
|
|
CopyBits work, and retain the CopyBits code in your application, so
|
|
users with special monitors (accellerator cards, PowerBook color
|
|
screens, Radius Pivot screens) can still play your game. (non-game
|
|
applications don't need more speed than CopyBits can give at its max.
|
|
Promise!)
|
|
|
|
5.3) Q: What is the fastest way to set one pixel?
|
|
|
|
A: On 68k Macs, NOT SetCPixel()! Assuming you have the correct ForeColor()
|
|
set, you can set the pen size to (1,0) and call Line (0,1)
|
|
|
|
I have heard PaintRect is good for this but requires slightly more code.
|
|
Using PaintRect eliminates a trap call.
|
|
|
|
5.4) Q: Why do pictures I record suddenly draw as empty space or not
|
|
draw at all?
|
|
|
|
A: When recording pictures, you have to set the clipping area to exactly
|
|
the frame of the picture you are recording. This is because it is
|
|
initally set at -32768,32727 in both directions, and offsetting the
|
|
picture even one pixel when drawing it will result in the region
|
|
wrapping around and becoming empty.
|
|
|
|
When recording pictures, do this:
|
|
|
|
*code*
|
|
PicHandle h = OpenPicture ( & theRect ) ;
|
|
ClipRect ( & theRect ) ;
|
|
/* draw the picture */
|
|
ClosePicture ( ) ;
|
|
*end*
|
|
|
|
5.5) Q: Where can I find the format of picture files and
|
|
resources?
|
|
|
|
A: The format of a picture resource version 1 is defined in a technical
|
|
note. This format is obsolete.
|
|
|
|
The format of a picture resource version 2 is defined in Old Inside Mac
|
|
vol V, with addenda in Old Inside Mac vol VI.
|
|
|
|
Some things happen with QuickTime compressed pictures; try the Inside
|
|
Mac: QuickTime book or turn to Inside Mac: Imaging with QuickDraw which
|
|
is the definite reference on QuickDraw.
|
|
|
|
The format of a picture file is the same as that of a picture resource
|
|
with 512 added 0 bytes in front.
|
|
|
|
5.6) Q: GWorlds?
|
|
|
|
A: What about them? They're great. Look them up in IM: Imaging With
|
|
QuickDraw. Don't forget to SetGWorld back to what it was before calling
|
|
WaitNextEvent.
|
|
|
|
5.7) Q: How do I find the current depth of the screen?
|
|
|
|
A: My question to you is: What screen? Many macs have more than one
|
|
screen attached. You can use GetDeviceList and walk the devices to find
|
|
the screen you're looking for (use TestDeviceAttribute to see whether
|
|
it's a screen) or you can call GetMaxDevice() to find the deepest device
|
|
your window intersects.
|
|
|
|
Once you have the device handle, finding the depth is just a
|
|
matter of looking at the gdPMap pixMapHandle, and dereference it
|
|
to the pmSize field. Done.
|
|
|
|
5.8) Q: Why is it a bad idea to draw directly to screen?
|
|
|
|
A: Because of several reasons:
|
|
|
|
- You will be incompatible with future display hardware.
|
|
|
|
- You will be incompatible with some present-day display
|
|
hardware, such as Radius Pivots and PowerBook color screens.
|
|
|
|
- You have to think about a lot of things; testing it all on
|
|
your own machine is not possible and the chances of crashing are
|
|
great.
|
|
|
|
- You will be incompatible with future hardware where devices
|
|
may live in some unaccessible I/O space.
|
|
|
|
5.9) Q: But I really need to do it. I can't make my animation into a
|
|
QuickTime movie, and CopyBits is too slow, even when syncing to the
|
|
screen retrace and with my source GWorld aligned properly.
|
|
|
|
A: You have to prepare yourself, and ask these questions:
|
|
|
|
- Do I want to support all screens, or just 8-bit devices?
|
|
|
|
- Do I have a few weeks of free time to make it work?
|
|
|
|
- Do I want to get nasty mail when I break on some hardware and
|
|
have to rev the application - even if I may not be able to get
|
|
ahold of the hardware that makes it break?
|
|
|
|
If all you're doing is rendering an image pixel-by-pixel or
|
|
line-by-line, maybe you can draw directly into an offscreen
|
|
pixMap/GWorld and then CopyBits the entire GWorld to screen?
|
|
That will be more compatible, especially if you use the
|
|
keepLocal flag when creating the GWorld.
|
|
|
|
5.10) Q: Okay, so how do I get the base address of the screen?
|
|
|
|
A: "The" screen? Which screen? There may be several. The base
|
|
address may be on an accellerated screen card. There may be more
|
|
than one screen covering the same desktop area.
|
|
|
|
Due to unfortunate circumstances, there is a bug in
|
|
GetPixBaseAddr() that causes it to return incorrect results for
|
|
early versions of System 7. Instead, get the baseAddr directly
|
|
from the gdPMap handle of the GDHandle for the screen you draw
|
|
to. This address may need switching to 32bit mode to be valid.
|
|
|
|
5.11) Q: Quit stalling and give me code!
|
|
|
|
A: Okay, but I'll let you sweat over Inside Mac to figure out
|
|
what it does. All of it is important; believe me! To make this
|
|
code run faster, a lot of the things it does can be done once
|
|
before starting to draw.
|
|
|
|
Make sure that you have a window that covers the area where you
|
|
are drawing, so other windows will not be overdrawn. Also make
|
|
sure that you do not do direct-to-screen-drawing while you are
|
|
in the background.
|
|
|
|
*code*
|
|
/* This is presently untested code */
|
|
/* Value is dependent on what depth the screen has */
|
|
/* This code doesn't work on non-color-quickdraw Macs (i e the MacClassic) */
|
|
/* "where" is in GLOBAL coordinates */
|
|
void
|
|
SetPixel ( Point where , unsigned long value ) {
|
|
|
|
Rect r ;
|
|
GDHandle theGD ;
|
|
char * ptr ;
|
|
long rowBytes ;
|
|
short bitsPerPixel ;
|
|
PixMapHandle pmh ;
|
|
Boolean oldMode ;
|
|
|
|
r . left = where . h ;
|
|
r . top = where . v ;
|
|
r . right = r . left + 1 ;
|
|
r . bottom = r . top + 1 ;
|
|
theGD = GetMaxDevice ( & r ) ;
|
|
if ( theGD ) {
|
|
where . v -= ( * theGD ) -> gdRect . left ;
|
|
where . h -= ( * theGD ) -> gdRect . top ;
|
|
pmh = ( * theGD ) -> gdPMap ;
|
|
rowBytes = ( ( * pmh ) -> rowBytes ) & 0x3fff ;
|
|
ptr = ( char * ) ( * pmh ) -> baseAddr ;
|
|
bitsPerPixel = ( * pmh ) -> pixelSize ;
|
|
oldMode = true32b ;
|
|
ptr += where . v * rowBytes ;
|
|
SwapMMUMode ( & oldMode ) ;
|
|
switch ( bitsPerPixel ) {
|
|
case 1 :
|
|
if ( value & 1 ) {
|
|
ptr [ where . h >> 3 ] |= ( 128 >> ( where . h & 7 ) ) ;
|
|
} else {
|
|
ptr [ where . h >> 3 ] &= ~( 128 >> ( where . h & 7 ) ) ;
|
|
}
|
|
break ;
|
|
case 2 :
|
|
ptr [ where . h >> 2 ] &= ( 192 >> 2 * ( where . h & 3 ) ) ;
|
|
ptr [ where . h >> 2 ] |= ( value & 3 ) << 2 * ( 3 - ( where . h & 3 ) ) ;
|
|
break ;
|
|
case 4 :
|
|
ptr [ where . h >> 1 ] &= ( where . h & 1 ) ? 0xf : 0xf0 ;
|
|
ptr [ where . h >> 1 ] |= ( value & 15 ) << 4 * ( 1 - ( where . h & 1 ) ) ;
|
|
break ;
|
|
case 8 :
|
|
ptr [ where . h ] = value ;
|
|
break ;
|
|
case 16 :
|
|
( ( unsigned short * ) ptr ) [ where . h ] = value ;
|
|
break ;
|
|
case 32 :
|
|
( ( unsigned long * ) ptr ) [ where . h ] = value ;
|
|
break ;
|
|
default :
|
|
abort ( ) ; /* Should never get here */
|
|
}
|
|
SwapMMUMode ( & oldMode ) ;
|
|
}
|
|
}
|
|
*end*
|
|
|
|
*6* Text
|
|
|
|
6.1) Q: How do I get TextEdit to display more than 32k of text?
|
|
|
|
A: You don't. Truly, it's not worth it. There's a call-for-call
|
|
TextEdit replacement called TE32k which does > 32k text, and is
|
|
available from any recent Info-Mac mirror. It doesn't do styled text,
|
|
though.
|
|
|
|
6.2) Q: How do I get TextEdit to display more than 32k of __styled__
|
|
text *and* embedded objects in the text (such as pictures)?
|
|
|
|
WASTE, available at ftp://ghost.dsi.unimi.it/pub2/papers/piovanel, is a
|
|
vast improvement over TextEdit. Version 1.0 does >32k styled text
|
|
retains compatibility with the TextEdit style scrap (which is used to
|
|
store styled text in files such as SimpleText's, as well as in the
|
|
clipboard), includes source code and is freeware. Really worth the
|
|
download. Version 1.1 adds embedded objects within the text, such as
|
|
pictures, intelligent cut-and-paste, built-in Drag Manager support,
|
|
built-in Undo support. 1.1 is currently in alpha, but seems to be very
|
|
stable.
|
|
|
|
"But," you nervously stutter, "WASTE is in Pascal! And it's munged so
|
|
that it won't work as an imported library w/Metrowerks C! What now?"
|
|
|
|
Dan Crevier is maintaining a C port of WASTE, and the current version
|
|
along with other WASTE goodies is at <ftp://rhino.harvard.edu/pub/dan/>.
|
|
|
|
6.3) Q: I'm too back-asswards to use WASTE 1.1. How do I include
|
|
pictures in text using TextEdit?
|
|
|
|
A: There's no really easy way (such as a TEAddPict() call), and it will
|
|
be a nasty kludge if you do get it working, but if you can live with
|
|
that, here's how to do it. I do recommend that you take a look at Q
|
|
6.2, above.
|
|
|
|
Write an algorithm to get the position of a special marker character
|
|
[Teach/SimpleText uses option-space] or text attribute that the user
|
|
will insert wherever he wants a picture. Pass this position to a
|
|
function similar to the one below.
|
|
|
|
*code*
|
|
/*
|
|
TEDrawPicture
|
|
Draw a picture within TextEdit's text.
|
|
|
|
input:
|
|
pos - the position of the special character in the text where the user
|
|
wants a picture.
|
|
r - size of picture
|
|
|
|
output:
|
|
r - frame in which picture was drawn
|
|
*/
|
|
|
|
void TEDrawPicture(short pos,PicHandle pic,Rect &r,TEHandle theTE)
|
|
{
|
|
Point bottomLeft; //I think TT/ST uses topleft
|
|
|
|
bottomLeft = TEGetPoint(pos, theTE);
|
|
|
|
r.right = bottomLeft.h + (r.right - r.left);
|
|
r.top = bottomLeft.v - (r.bottom - r.top);
|
|
r.left = bottomLeft.h;
|
|
r.bottom = bottomLeft.v;
|
|
|
|
DrawPicture(pic, &r);
|
|
}
|
|
|
|
*end*
|
|
|
|
I'll leave selection and hiliting as an exercise for the reader (don't
|
|
ya love it when people say that?).
|
|
|
|
Thereotically, it should be possible to kludge up TextEdit to the point
|
|
where it would treat pictures as if they were actually letters (rather big
|
|
letters, but letters just the same). That's what the width and word break
|
|
hooks are for, after all. However, this would be a lot of Work, and I've
|
|
never seen it done. One is lead to believe that it's less work to create
|
|
an improved version of TextEdit from the ground up with picture support.
|
|
WASTE 1.1, in fact, does this rather nicely.
|
|
|
|
6.4) Q: I have all this money, and I want to get rid of it. How do I
|
|
edit more than 32k of styled text now?
|
|
|
|
A: There are at least three solutions.
|
|
|
|
1) The Galaxy application framework comes with a styled text editting
|
|
engine which does more than 32k of text. It also happens to support
|
|
cross-platform application development. Pricing starts at $10000.
|
|
<galaxy@visix.com>
|
|
|
|
2) DataPak is selling a cross-platform library called "PAIGE". It is
|
|
written to be customizable to any extent, and you can do _anything_ in
|
|
it (want quicktime movies that play and flow with the text while
|
|
editting? Three pages of code; you can adapt their picture sample code.)
|
|
Available for Mac, Windows & Never Trusted and Power Mac. Pricing at
|
|
$5000 ($25000 for source code) - it might be cheaper if you talk to
|
|
them. Customer support is reputed to be "lousy".
|
|
|
|
3) Or you could use WASTE 1.1 with it's embedded objects implementation
|
|
(want quicktime movies that play and flow with the text while editing?
|
|
One page of code, if that much.)
|
|
|
|
6.5) Q: How do I convert from a string to a floating point type?
|
|
|
|
A: Once you've got an Str255, you want to call the routine
|
|
StringToExtended to change the number into type extended80, which is the
|
|
80-bit floating point type. The nice thing about StringToExtended is
|
|
that it even works in funky foreign language scripts like Chinese. To
|
|
use the routine, you must pass it not only the Str255 that you want
|
|
converted, but also the results of the StringToFormatRec routine and the
|
|
GetIntlResourceTable routine. The documentation is generally difficult,
|
|
so I'll describe the parameters and give you a code example below.
|
|
Here's what you pass to StringToExtended:
|
|
|
|
- source:
|
|
Obviously the string representation of the number.
|
|
|
|
- myFormatRec:
|
|
This is simply the format that you expect the number to be. For
|
|
example, if you wanted a positive integer with up to 3 decimal places,
|
|
you would want the format to be "###". (The "#" symbol means a non-zero
|
|
filled digit, whereas a "0" would mean zero filled.) If you wanted an
|
|
floating point exponential notation with up to 2 digit integer portion,
|
|
exactly 2 digit decimal portion, and exactly 1 digit after the "E", your
|
|
format would be "##.00E+0". (Actually, in Canada, you folks might use a
|
|
"," instead of a "." for the decimal point; if you do, then you would
|
|
put the locally correct symbol in there.) In a format string, you can
|
|
put the format for a positive value, a negative value, and 0 seperated
|
|
by semicolons (e.g. "##.00E+0;-##.00E+0;0.00E+0").
|
|
|
|
But myFormatRec is not the format string itself, but is an internal
|
|
format that you get from calling StringToFormatRec. This is so you can
|
|
store the format returned to you by StringToFormatRec and use it on
|
|
different international systems. There is a nice editor for ResEdit for
|
|
'FMAT' resources that lets you type the format string and will call
|
|
StringToFormatRec for you and create an 'FMAT' resource out of the
|
|
result. Then you can load the 'FMAT' at run time and pass it to
|
|
myFormatRec.
|
|
|
|
- partsTable:
|
|
The number parts table from the 'itl4' resource. If you are using
|
|
System 7 or later, you call GetIntlResourceTable, asking it for the
|
|
number parts table. You don't need to worry about HLock'ing itlHandle
|
|
because StringToExtended doesn't move memory; just don't do anything
|
|
between your call to GetIntlResourceTable and the StringToFormatRec
|
|
routine. If you are using System 6, you need to perform the
|
|
GetIntlResourceTable by hand. It's a few lines of code; left as an
|
|
exercise to the reader.
|
|
|
|
- x:
|
|
The extended number to put the thing into.
|
|
|
|
So, let's say you expect the user to enter a string containing up to 5
|
|
digits in the integer with a thousand marker between the 3rd and fourth
|
|
digit, exactly two digits after the decimal, put it in parenthesis if
|
|
it's negative, and have it just be "0.00" if it's 0. (I will use "."
|
|
for the decimal and "," for the thousand marker. Here's the C code
|
|
(passing in the source string):
|
|
|
|
*code*
|
|
Handle itlHandle; /* The 'itl4' resource handle */
|
|
long offset, length; /* Offset-length of parts table */
|
|
NumFormatStringRec myFormatRec; /* Canonical format record */
|
|
extended80 x; /* The number to put it into */
|
|
|
|
GetIntlResourceTable (smCurrentScript, smNumberPartsTable,
|
|
&itlHandle, &offset, &length);
|
|
StringToFormatRec ("\p##,###.00;(##,###.00);0.00",
|
|
(NumberParts *)(*itlHandle + offset),
|
|
&myFormatRec);
|
|
StringToExtended (source, &myFormatRec,
|
|
(NumberParts *)(*itlHandle + offset),
|
|
&x);
|
|
*end*
|
|
|
|
If you saved a format record in a resource using the 'FMAT' editor
|
|
(which is really the preferred way to do it), you would change the code
|
|
to look like this:
|
|
|
|
*code*
|
|
Handle itlHandle; /* The 'itl4' resource handle */
|
|
long offset, length; /* Offset-length of parts table */
|
|
NumFormatStringRec **myFormatRec; /* Canonical format resource */
|
|
extended80 x; /* The number to put it into */
|
|
|
|
myFormatRec = (NumFormatStringRec **)GetResource('FMAT', MY_FMAT);
|
|
GetIntlResourceTable (smCurrentScript, smNumberPartsTable,
|
|
&itlHandle, &offset, &length);
|
|
StringToExtended (source, *myFormatRec,
|
|
(NumberParts *)(*itlHandle + offset),
|
|
&x);
|
|
*end*
|
|
|
|
The StringToExtended routines will return a result that will tell you if
|
|
there are any parsing errors. Error checking is also left as an
|
|
exercise to the reader.
|
|
|
|
Of course, the reverse of the process (using ExtendedToString) works
|
|
very much the same way, passing the same sorts of parameters.
|
|
|
|
*7* Communications and Networking
|
|
|
|
7.1) Q: How do I get at the serial ports?
|
|
|
|
A: You call OpenDriver for the names "\p.AOut" and "\p.AIn" to get at
|
|
the modem port, and "\p.BOut" and "\p.BIn" for the printer port. The
|
|
function RAMSDOpen was designed for the original Mac with 128 kB of
|
|
memory and 64 kB of ROM, and has been extinct for several years.
|
|
|
|
However, many users use their serial ports for MIDI, LocalTalk, graphic
|
|
tablets, or what have you and have installed an additional serial port
|
|
card to get more ports. What you SHOULD do as a good application is to
|
|
use the Comm Toolbox Resource Manager to search for serial resources;
|
|
this requires that the Comms Toolbox is present (true on earlier System
|
|
6 with an INIT, on later System 6 and System 7 always, as well as on
|
|
A/UX) and that you have initialized the comms resource manager. The
|
|
exact code follows (adapted from Inside Mac Comms Toolbox):
|
|
|
|
*code*
|
|
#include "CommResources.h"
|
|
OSErr
|
|
FindPorts ( Handle * portOutNames , Handle * portInNames , Handle * names , Handle * iconHandles ) {
|
|
|
|
OSErr ret = noErr ;
|
|
short old = 0 ;
|
|
CRMRec theCRMRec , * found ;
|
|
CRMSerialRecord * serial ;
|
|
|
|
* portOutNames = NewHandle ( 0L ) ;
|
|
* portInNames = NewHandle ( 0L ) ;
|
|
* names = NewHandle ( 0L ) ;
|
|
* iconHandles = NewHandle ( 0L ) ;
|
|
while ( ! ret ) {
|
|
theCRMRec . crmDeviceType = crmSerialDevice ;
|
|
theCRMRec . crmDeviceID = old ;
|
|
found = ( CRMRec * ) CRMSearch ( ( QElementPtr ) & theCRMRec ) ;
|
|
if ( found ) {
|
|
serial = ( CRMSerialRecord * ) found -> crmAttributes ;
|
|
old = found -> crmDeviceID ;
|
|
PtrAndHand ( & serial -> outputDriverName , * portOutNames ,
|
|
sizeof ( serial -> outputDriverName ) ) ;
|
|
PtrAndHand ( & serial -> inputDriverName , * portInNames ,
|
|
sizeof ( serial -> inputDriverName ) ) ;
|
|
PtrAndHand ( & serial -> name , * names ,
|
|
sizeof ( serial -> name ) ) ;
|
|
PtrAndHand ( & serial -> deviceIcon , * iconHandles ,
|
|
sizeof ( serial -> deviceIcon ) ) ;
|
|
} else {
|
|
break ;
|
|
}
|
|
}
|
|
return err ;
|
|
}
|
|
*end*
|
|
|
|
This will create four handles with the driver names, device names and
|
|
driver icon handles for all of the available serial devices. Then let
|
|
the user choose with a pop-up menu or scrolling list, and save the
|
|
choice in your settings file.
|
|
|
|
You can use OpenDriver, SetReset, SetHShake, SetSetBuf, SerGetBuf and
|
|
the other Serial Manager functions on these drivers. To write to the
|
|
serial port, use FSWrite for synchronous writes that wait until all is
|
|
written, or PBWrite asynchronously for queuing up data that is supposed
|
|
to go out but you don't want to wait for it. At least once each time
|
|
through your event loop, you should call SerGetBuf on the in driver
|
|
reference number you got from OpenDriver, and call FSRead for that many
|
|
bytes - neither more nor less.
|
|
|
|
If you are REALLY interested in doing the right thing, you will use the
|
|
Communications Toolbox Connection Manager instead; this will give you
|
|
access to modems, direct lines, and networks of various kinds using the
|
|
same API! Great for stuff like BBSes that may be on a network as well
|
|
etc. The Comms Toolbox also provides modularized terminal emulation
|
|
and file transfer tools, although the Apple-suplied VT102 tool is pretty
|
|
lame, as is the VT102 mode of the VT320 tool. And it seems as though
|
|
it was designed by people who'd never used a Mac before... more in the
|
|
Unix style, right down to the lack of documentation and "magicCookie."
|
|
|
|
7.2) Q: Where is a Berkley sockets library for the Mac?
|
|
|
|
A: There are some problems with that. MacTCP, the Mac Toolbox
|
|
implementation of TCP/IP, doesn't have an API that looks at all like
|
|
Berkley sockets. For instance, there is ONE paramater-block call to do
|
|
a combined listen()/accept()/bind() - sort of. I have heard that there
|
|
may be a socket library available by ftp from MIT but haven't seen it
|
|
myself.
|
|
|
|
There is also a pretty good C++ TCP implementation called GUSI which is
|
|
easily handled, and it also is callable from C using the Berkley socket
|
|
API. Apart from TCP, it also handles "standard" Mac network protocols
|
|
such as ADSP. The big disadvantage is that it is currently only
|
|
implemented for MPW. The ftp site is nic.switch.ch,
|
|
software/mac/src/mpw_c.
|
|
|
|
I can also recommend the Communications Toolbox; for the price of using
|
|
an API that is a bigger pain in the ass than configuring Windoze to use
|
|
a new peripheral device, you get the benefit of being able to use any
|
|
kind of connection (TCP tools are available).
|
|
|
|
Instead of the Comm Toolbox, one might use Apple's much improved Open
|
|
Transport architecture. Preliminary docs are available for ftp at
|
|
seeding.apple.com. Apple's new networking products team seems to have
|
|
it's head screwed on tight. A refreshing change.
|
|
|
|
Novell and Wollogong offer commercial socket-like libraries.
|
|
|
|
7.3) Q: Where do I find MacTCP?
|
|
|
|
A: You can buy the MacTCP developers kit from APDA. It is also
|
|
available on E T O, and if you want saner headers than those, try ftp to
|
|
seeding.apple.com. MacTCP (the control panel) is included with System
|
|
7.5 and above.
|
|
|
|
7.4) Q: I'm trying to write to the serial port. It works fine on the
|
|
following Machines, Quadra700, IIFX, Powerbook 170, Quadra 840av, but
|
|
freezes on the Duo 230 and 280c.
|
|
|
|
A: You need to call SerHShake. Otherwise you get screwed on some
|
|
machines without a hardware handshaking cable because the port default to
|
|
hardware handshaking.
|
|
|
|
*8* IAC
|
|
|
|
8.1) Q: What are AppleEvents?
|
|
|
|
A: AppleEvents are a level-5 network protocol. If you are not familiar
|
|
with the ISO network stack, this means it's a way of structuring sessions
|
|
between network entities (programs) that is not dependent on the
|
|
underlying protocol (such as PPC or TCP/IP) Despite being a network
|
|
protocol, they can be very useful on Macs that are not on a network. In
|
|
short, they provide applications with a comprehensive way to send
|
|
arbitrary structured data to other applications (or themselves) which
|
|
receive the events through their main event loop.
|
|
|
|
The AppleEvent Object Model is a way of looking at applications and the
|
|
data they contain, and also a level-6 network protocol. You _can_ send
|
|
AppleEvent Object Model data through AppleEvents (and the standard
|
|
AppleEvents defined in the AppleEvent Registry use it) but you don't have
|
|
to - unless you want to talk with other applications, of course, then the
|
|
AEOM is a lingua franca.
|
|
|
|
8.2) Q: What are the four required AppleEvents?
|
|
|
|
A: There are four events your application really must implement if you
|
|
want to sell it: the kCoreEventClass class, kAEOpenApplication,
|
|
kAEQuitApplication, kAEOpenDocuments and kAEPrintDocuments events IDs.
|
|
When you support these events (or any AppleEvents) you will not get
|
|
startup info through GetAppParams() anymore, unless you run under System
|
|
6 of course. The kAEOpenApplication event will be sent to you when the
|
|
user double-clicks your app and it's not started yet. When receiving it,
|
|
you can put up a new untitled window.
|
|
|
|
kAEOpenDocuments is sent when the user double-clicks your apps documents.
|
|
Note that if the first AppleEvent you receive is a kAEOpenDocuments
|
|
event, the user started your app by double-clicking its documents.
|
|
|
|
kAEPrintDocuments is sent when the user selects your documents and
|
|
chooses "Print" in the Finder menu. If this is the first AppleEvent you
|
|
receive, you should print the documents and then quit the application
|
|
again; if you received a kAEOpenApplication or kAEOpenDocuments event
|
|
before this, you should just print the documents and close them when
|
|
you're done.
|
|
|
|
kAEQuitApplication is sent to you when the user chooses "Shutdown" or
|
|
"Restart" from the Apple Menu. You should ask the user whether he wants
|
|
to save any unsaved changed documents, and then quit unless the user
|
|
presses Cancel.
|
|
|
|
Interestingly enough, you can use these four AppleEvents to send even to
|
|
non-AE-aware applications, and the system will translate these events
|
|
into fake menu selections for you.
|
|
|
|
A good way of shutting down the Finder is to send it a Quit AppleEvent.
|
|
You should send a Quit AppleEvent to File Sharing Extension before you
|
|
shut down the Finder, though; the FSE is found by looking for a process
|
|
with the creator 'hhgg'.
|
|
|
|
8.3) Q: Are there any limits or tradeoffs with AppleEvents?
|
|
|
|
A: As always, more power means more responsibility.
|
|
|
|
AppleEvents sent to applications on other Macs require authentification
|
|
the first time they are sent. If the remote Mac allows Guests to link to
|
|
programs, the INIT AutoGuest 2.0 might help (or the code solution that
|
|
comes with it and you can build into your application)
|
|
|
|
In the first version of the AppleEvent manager, there was a total 64K
|
|
limit on the size of data and overhead. This limit has been lifted with
|
|
the version of the AppleEvent manager that comes with AppleScript.
|
|
|
|
AppleEvents require a lot of memory copying and handle resizing in their
|
|
construction; this means that large AppleEvents may be slow in
|
|
construction, especially when compared to a pure PPC Toolbox or
|
|
ADSP/ASDSP link. The way around this is to use Jens Alfke's AEGizmos,
|
|
available on the Developer CD, to create AppleEvents. AEGizmos are
|
|
being integrated into System Software, so You Will be doing the right
|
|
thing.
|
|
|
|
You should use your own application signature as event class for
|
|
AppleEvents you make up, in order not to collide with anybody else.
|
|
Other than that, you are free to make your own events for your own
|
|
needs, though supporting the required events and at least a subset of
|
|
the Core event suite will buy you a lot of functinality from within
|
|
AppleScript. Especially important are the Get Current Selection and Set
|
|
Current Selection events (which are really Get/Set Data on the contents
|
|
of the current selection of the application)
|
|
|
|
The signature for your application SHOULD be registered with DTS to
|
|
avoid conflicts; this is done through e-mail to
|
|
DEVSUPPORT@AppleLink.Apple.Com and the form you use is located on the
|
|
developer CDs and found on ftp.apple.com.
|
|
|
|
8.4) Q: How do AppleEvents interface with AppleScript?
|
|
|
|
A: AppleEvents are the meat and potatoes of AppleScript. If you support
|
|
the AppleEvent Object Model from within your application, users can
|
|
control you through AppleScript.
|
|
|
|
The first thing you should do is get ahold of Inside Mac:
|
|
Interapplication Communication, and a copy of the AppleEvents Registry.
|
|
The former tells you all you ever need to know about AppleEvents, while
|
|
the latter is paramount for implementing the right standard events. If
|
|
everybody use the standard events, dynamic data interchange between any
|
|
applications will become sweet reality!
|
|
|
|
Then there is the 'aete' resource which lets you put names on the events
|
|
you support, so that users can "Open Terminology" on your application
|
|
from within the Apple Script Editor and use the proper AppleScript
|
|
commands in their scripts. The format of an aete resource is defined in
|
|
Inside Macintosh: Interapplication Communication.
|
|
|
|
8.5) Q: Can I compile and run scripts from within my application?
|
|
|
|
A: Yes, this is very simple. There are toolbox calls for reading
|
|
scripts, compiling scripts, and executing scripts. (OSACompile,
|
|
OSAExecute) These are all documented in Inside Mac: Interapplication
|
|
Communication.
|
|
|
|
8.6) Q: Is this a good way of getting a macro language almost
|
|
for free?
|
|
|
|
A: "Good" is an understatement. Just let users write scripts, load them
|
|
into menu items and go. Total systems integration in under a week,
|
|
including adding support for the AEOM to your application.
|
|
|
|
There is source code for an application called "MenuScripter" on the
|
|
developer CD which shows you how to do an application with all of the
|
|
menus being AppleScript scripts.
|
|
|
|
8.7) Q: Why do I get error -903 (noPortErr) when I try to send an Apple
|
|
Event?
|
|
|
|
A: Make sure the isHighLevelEventAware flag in your application's SIZE
|
|
resource is set. The AE Manager won't allow you to send events if you're
|
|
not able to receive them.
|
|
|
|
*9* Standalone Code & Trap Patching
|
|
|
|
9.1) Q: How do I do code resources/extensions/external functions, much
|
|
like HyperCard XCMDs only for my 68k app/extension?
|
|
|
|
A: Here is what you need to do:
|
|
|
|
Define a storage location for the plug-ins. such as, for an application
|
|
called Foo, a folder called "Foo Pouch/ PlugIns/ Modules/ Tools/ Etc",
|
|
which your installer creates, and which you search for in the same
|
|
folder as your application, the preferences folder, and the System
|
|
Folder (for System 6 (no preferences)) the name of the pouch folder
|
|
should be in a 'STR ' or 'STR#' resource for easy internationalization.
|
|
|
|
Next, define a resource type to hold your plug-in exectuable code. You
|
|
should allow any resID number, since some development systems have
|
|
restrictions on which id numbers can be used for multi-segment code
|
|
resources.
|
|
|
|
Decide whether you will allow multiple code resources per file. For
|
|
example, Photoshop lets you bundle an import resource, an export
|
|
resource, and a filter into the same file, each is its own resource
|
|
type. It uses the resource name to tell the user, so each has its own
|
|
name.
|
|
|
|
Decide on the user interface to plug-ins. Commonly, at program
|
|
start-up, you scan the pouch and collect all the files of the correct
|
|
types. Then you scan for appropriate code resources, then put the names
|
|
of the resources in the menus. You can also use the file names, or run
|
|
the code resources and ask them for the correct name.
|
|
|
|
Decide on the calling convention. MPW likes to pass parameters as
|
|
longs, and pascal development systems usually can't generate C
|
|
interfaces, so your best bet is to have the entry point of your code
|
|
resource be something like:
|
|
|
|
extern pascal long PlugIn(long selector, CallbackPtr callback,
|
|
long param1, long param2, long param3, long refcon);
|
|
|
|
where params 1 through 3 will have specific meanings depending upon
|
|
which function selector is asking to be performed.
|
|
|
|
CallbackPtr is something like this:
|
|
typedef struct CallbackRec{
|
|
DrawFunc erase;
|
|
DrawFunc paint;
|
|
}CallbackRec, *CallbackPtr;
|
|
|
|
where DrawFunc is something like:
|
|
typedef pascal void (*DrawFunc)(Rect *);
|
|
|
|
This is the place where you define services that your application will
|
|
perform when asked to by the code resource of the plug-in.
|
|
|
|
You'll need to define a bunch of selectors for what you want the plug-in
|
|
to do.
|
|
|
|
You should definately give the plug-in an Init selector, and a dispose
|
|
selector, and have Init return an error or a refcon, which will be
|
|
passed back to the plug-in on each call, so the plug-in can have some
|
|
persistent storage. You should definately set the CurResFile to the
|
|
plug-in's file while it is running, so it can easily get at any
|
|
resources it needs.
|
|
|
|
The Init selector should pass the interface version in param1 and the
|
|
program version in param2, so that the plug-in can cope with different
|
|
versions of your program.
|
|
|
|
The actual call to the plug-in looks like:
|
|
|
|
*code*
|
|
h = GetResource('PLUG', 1);
|
|
HLock(h);
|
|
xh = StripAddress(h);
|
|
((PlugInFunc) *xh)(kInit, callbacks, kInterfaceVer1, kProgVer1, 0, 0);
|
|
HUnlock(h);
|
|
*end*
|
|
|
|
The StripAddress is important; if your app is running in 24bit mode, the
|
|
resource handle may contain tag bits and you don't want strange things
|
|
to happen if the code resource switches into 32bit mode (which QuickDraw
|
|
may do, incidentally)
|
|
|
|
Exactly how you structure your calling conventions is up to you; there
|
|
is no accepted standard (except for HyperCard XCMDs, but that is
|
|
probably overkill for you).
|
|
|
|
9.2) Q: How do I fat-patch a trap (that is, how do I patch a trap with
|
|
both 68k and PPC code)?
|
|
|
|
A: Create a normal fat routine descriptor and pass it to
|
|
Set{Tool, OS}TrapAddress().
|
|
|
|
*10* Compatibility
|
|
|
|
10.1) Q: I see all these people call Gestalt without first
|
|
checking whether it's implemented. Isn't that bad?
|
|
|
|
A: No; Gestalt and a few other traps (the HXxx file manager
|
|
traps, and FindFolder) are implemented using glue so they do the
|
|
right thing even if the trap is not implemented.
|
|
|
|
If you want to get rid of the glue, you can #define
|
|
SystemSevenOrLater (and, using Think C/C++, re-pre-compile
|
|
MacHeaders) However, then you will be responsible for checking
|
|
for these features before you use them.
|
|
|
|
10.2) Q: What more functions are implemented in glue?
|
|
|
|
A: Wake Up and Smell the Glue!
|
|
|
|
How often have you wished you could use that cool new ToolBox
|
|
call, but didn't want to make your application System 7
|
|
dependent? Well, it might be that you *could* in fact have used
|
|
the call. Several traps are implemented in glue, that is, much
|
|
of their functionality is linked into your application and thus
|
|
available even if you are running under an old System.
|
|
|
|
This list applies to MPW 3.2 and should also be valid for the
|
|
current version of Think C. If you find any inaccuracies, please
|
|
report them to me. (neeri@iis.ee.ethz.ch)
|
|
|
|
FSOpen: Tries first OpenDF, then Open.
|
|
|
|
HOpenResFile: Full functionality emulated if trap not available
|
|
|
|
HCreateResFile: Full functionality emulated if trap not
|
|
available
|
|
|
|
FindFolder: Under System 6, understands the following values for
|
|
folderType and returns the System Folder for all of them:
|
|
|
|
kAppleMenuFolderType
|
|
|
|
kControlPanelFolderType
|
|
|
|
kExtensionFolderType
|
|
|
|
kPreferencesFolderType
|
|
|
|
kPrintMonitorDocsFolderType
|
|
|
|
kStartupFolderType
|
|
|
|
kSystemFolderType
|
|
|
|
kTemporaryFolderType
|
|
|
|
SysEnvirons: Full functionality emulated if trap not available
|
|
|
|
NewGestalt: Returns an error if not implemented
|
|
|
|
ReplaceGestalt: Returns an error if not implemented
|
|
|
|
Gestalt: The following selectors are always implemented:
|
|
|
|
vers mach sysv proc fpu
|
|
|
|
qd kbd atlk ram lram
|
|
|
|
10.3) Q: I have to support System 6, don't I?
|
|
|
|
A: It would be foolish to lock yourself out of the many benefits
|
|
the System 7 API provides for software that you start to write
|
|
now. Some of the System 6 and older things (likely SFGetFile and
|
|
wdRefNums among others) will be phased out of the interfaces and
|
|
lose support; especially on future platforms.
|
|
|
|
The installed base of System 7 is larger than that of System 6;
|
|
this is not surprising because Apple has been shipping System 7
|
|
for several years with all new machines, including the LCII,
|
|
Classic II, Performas and Color Classic. Another argument is
|
|
that newer computer owners (having System 7) are much more
|
|
likely to buy new software than old computer owners who have
|
|
systems that already do what they want them to.
|
|
|
|
The added work to support both System 6 and System 7 is
|
|
significant; if you have the time and money you may want to do
|
|
it, but only supporting System 6 and not System 7 is doomed to
|
|
fail in the market of today.
|
|
|
|
Some may call this position subjective; I call it business sense
|
|
based on market demographics. A rule of thumb may be that if you
|
|
target color machines only, you can just as well demand System 7
|
|
as well.
|
|
|
|
10.4) Q: Why does my application work on an SE with accellerator
|
|
(or a Mac II or Quadra), but not on one without?
|
|
|
|
A: Assuming you're not calling Color QuickDraw (which is not
|
|
available on accellerated SEs), you most probably have an
|
|
odd-aligned word access somewhere.
|
|
|
|
The 68000 does not allow words or longwords to be read from odd
|
|
addresses, while the 68020 and up relaxes this restriction (it
|
|
still is slower than aligned-word access though)
|
|
|
|
This may or may not crash depending on your compiler:
|
|
|
|
*code*
|
|
struct foo {
|
|
char c1 ;
|
|
char c2 ;
|
|
char c3 ;
|
|
char c4 ;
|
|
char c5 ;
|
|
} bar ;
|
|
|
|
long * x = ( long * ) & bar . c2 ;
|
|
* x = 0x12345678 ; /* X is odd if compiler doesn't pad */
|
|
|
|
This WILL crash on an SE/Plus/Classic/PB100:
|
|
|
|
char foo [ 10 ] ;
|
|
|
|
long * x = ( long * ) & foo [ 1 ] ;
|
|
* x = 0x12345678 ;
|
|
|
|
*end*
|
|
|
|
10.5) Q: Why does my application work on a IIci and a pre-1995 PowerMac
|
|
but not on a Quadra?
|
|
|
|
A: Two reasons:
|
|
|
|
1) The Quadras 900 and 950 have special processors that handle the serial
|
|
ports; if you write directly to the serial chips, you will crash (this
|
|
goes for the IIfx as well)
|
|
|
|
2) The Quadras have 68040 processors, as have the Centrises. These
|
|
processors have separate instruction and data caches (like the 68030) but
|
|
they are larger (4K each) and unlike the 68030 which is write-through
|
|
data cached, the 68040 is copy-back data cached. This means that changes
|
|
you make to "your code" aren't really changed all the time, since the
|
|
changes may still be in the data cache and not written to memory when the
|
|
CPU reads that part of memory into its I-cache. Even worse; that part
|
|
might already have been read into the I-cache before you change it in the
|
|
D-cache, meaning that writing out the D-cache will still not be enough.
|
|
You need to flush both the caches when writing self-modifying code.
|
|
|
|
Self-modifying code includes code that builds its own jump tables and
|
|
code that decrypts itself and code that "stubs" MDEFs or WDEFs to jump
|
|
back into the application code.
|
|
|
|
You flush the cache using FlushDataCache() which is implemented if
|
|
Gestalt says you have a 68020 or better processor (or if the _HwDispatch
|
|
trap is implemented)
|
|
|
|
The current PowerMac 68k emulator doesn't have the self-modifying cache
|
|
problem, but a future faster version will.
|
|
|
|
10.6) Q: Why does my application work on my Quadra but not on my
|
|
accellerated SE?
|
|
|
|
A: You're probably calling Color QuickDraw without first checking if it's
|
|
available. The following machines do not have color QuickDraw in ROM nor
|
|
RAM:
|
|
|
|
Mac Plus, Mac SE, Mac Classic, Mac Luggable, PowerBook 100, Outbound
|
|
|
|
10.7) Q: I do check for color quickdraw, but crash nevertheless.
|
|
|
|
A: _Gestalt lies under some versions of System 7; it says that non-color
|
|
machines HAVE color QuickDraw when you test using the
|
|
gestaltQuickdrawFeatures selector.
|
|
|
|
Instead, check the gestaltQuickdrawVersion selector, if it returns >=
|
|
gestalt8BitQuickdraw then you can safely use gestaltQuickdrawFeatures,
|
|
else you only have b/w QuickDraw.
|
|
|
|
*11* Optional System Software
|
|
|
|
*11.1* QuickTime
|
|
|
|
11.1.1) Q: I want to write a Amiga QuickTime player and need the
|
|
CODEC format details.
|
|
|
|
A: Although the structure of QuickTime movies is well documented in
|
|
Inside Mac: QuickTime, the inner workings of the Apple compression
|
|
modules is a trade secret that Apple will only license to you at great
|
|
cost. Perhaps it's time for a freeware, cross-platform QuickTime codec?
|
|
|
|
*12* Third-Party Solutions
|
|
|
|
*12.1* Databases
|
|
|
|
12.1.1) Q: What are some royalty-free databases available for the
|
|
Macintosh?
|
|
|
|
A: These are commercial with no run-time licenses:
|
|
|
|
- Prograph CPX comes with a database that can do indexes and tables.
|
|
<sales@prograph.com>
|
|
|
|
- CXBase Pro is an engine that comes with source, does tables and indexes
|
|
in one compound file. <tse.int@applelink.apple.com>
|
|
|
|
- dtF is a relational database library. <DTF.AMERICA@applelink.apple.com>
|
|
|
|
NeoAccess is an object-oriented database, where you can store objects and
|
|
retrieve by field value; it handles inheritance as well. Comes as a
|
|
demo on the CodeWarrior CD with an unlockable archive of the real thing.
|
|
|
|
12.1.2) Q: I need a robust Client/Server database library. What do I do?
|
|
|
|
A: Get the Macintosh Client/Server Database Development Summary, by Liam
|
|
Breck. It covers software applicable to Macintosh (and cross-platform)
|
|
client/server database development in three categories:
|
|
|
|
+ Client application development tools
|
|
+ Data access layers
|
|
+ Database servers
|
|
|
|
The eight page (20 Kbytes ASCII text) document includes explanations of the
|
|
three categories and describes over 30 products. Its sources are vendors'
|
|
product literature, industry periodicals, and discussions with users and
|
|
vendors' tech support staff. It is purely informational and contains no
|
|
propaganda, as the author is a neutral party.
|
|
|
|
To receive a copy electronically, email a request to:
|
|
<maccsdb@external.umass.edu>. Tell 'em the Mac Programming FAQ sent
|
|
you!
|
|
|
|
*12.2* Circumvention of Toolbox Limitations
|
|
|
|
12.2.1) Q: Help! The List Manager is driving me right UP THE WALL! I
|
|
want to throw it out and start over. What'r my options?
|
|
|
|
A: The only non-framework List Manager replacement of which I'm aware is
|
|
StoneTable, a commerical replacement library for the List Manager which
|
|
provides many extensions including variable size columns/rows,
|
|
column/row titles, different style/font/size/color per cell, sorting,
|
|
edit in cell, and much more. <http://www.teleport.com/~stack>
|
|
|
|
TCL, PowerPlant, and MacApp all have their own integrated list
|
|
management solutions.
|
|
|
|
*13* Dessert
|
|
|
|
13.1) Q: Dessert?
|
|
|
|
A: Honey Hill Farms Cookie Jar Frozen Yoghurt or Haagen-Dazs Raspberry &
|
|
Cream Ice Cream.
|
|
|
|
Hokey-Pokey icecream with chocolate sauce and (for those who like their
|
|
brain food firmer) Almond and Double Chocolate CookieTime cookies!?
|
|
|
|
*14* Contributors
|
|
|
|
[do let me know if I've forgotten you]
|
|
|
|
Denis Birnie
|
|
Liam Breck
|
|
Scott Bronson <urge@mcl.mcl.ucsb.edu>
|
|
Tim Converse <converse@cs.uchicago.edu>
|
|
Bob Hablutzel
|
|
Julian Harris
|
|
Bruce Hoult <Bruce@hoult.actrix.gen.nz>
|
|
Peter Jensen <pjensen@netcom.com>
|
|
Steve Jasik <macnosy@jasik.com>
|
|
Jonathan Kimmitt <jrrk@camcon.co.uk>
|
|
Matthias Neeracher <neeri@iis.ee.ethz.ch>
|
|
David P. Oster <oster@netcom.com>
|
|
Louis M. Pecora
|
|
Ingemar Ragnemalm <ingemar@lysator.liu.se>
|
|
Pete Resnick <resnick@uiuc.edu>
|
|
Phil Shapiro <phils@bedford.symantec.com>
|
|
eric slosser <slosser@apple.com>
|
|
M Sooriarachchi
|
|
Bill <stack@teleport.com>
|
|
Chris Thomas <thunderone@delphi.com>
|
|
Doug W. <dougw@as.arizona.edu>
|
|
Jon Watte <h+@austin.metrowerks.com>
|
|
Rick Zaccone <zaccone@bucknell.edu>
|
|
|
|
|
|
--
|
|
-- Jon W{tte, h+@nada.kth.se, Mac Software Engineer Deluxe --
|
|
|
|
Clearly, most humans are not rational beings; they are rationalizing beings.
|
|
-- Mel Walker
|