home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-04-11 | 86.1 KB | 2,071 lines |
- Archive-name: macintosh/programming-faq
-
- The Public Domain Mac Programming FAQ Answer Sheet
- Last update: 16 Feb 95 "Early Morning Cold FAQ"
-
- [out of town March 6, so this FAQ is set to expire in little over 2 weeks]
-
- 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). This sheet was started and is distributed by Jon W"atte,
- whom you may reach as <h+@nada.kth.se>.
-
- 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. An
- HTML version is available.
-
- 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 to search for: patmos, boycott of Apple, floating
- point type, Client/Server
-
- 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, strings to floats
- 7. Communications and Networking
- Serial ports, TCP/IP, sockets
- 8. Interapplication Communication
- AppleEvents, OSA, Scripting, and You
- 9. Dynamic Linking
- the dynamics of external code resources
- 10. Compatibility
- gestalt & glue
- 11. Optional System Software
- 11.1. QuickTime
- codec details and the lack thereof
- 12. +Third-Party Solutions
- databases
- 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 or Centris 650 or better is
- almost a must; remember that your time costs your employer much more than
- just your salary. A PowerMac is preferable. 16 MB is a minimum to run at
- all comfortably, 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 need a development system such as Think C, CodeWarrior C++, MPW C 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; one of which Apple's own CD300 is a very good buy at the time of
- writing this. 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. <apda@appplelink.apple.com>
-
- 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, or Sydow: Think THINK C
- might help (the latter uses the Think C compiler, while the former can
- be used with any C++ compiler)
-
- Another tool which many find a must-have is the Think Reference version
- 2.0.1, containing reference material on the most used parts of the Mac
- toolbox with lightning-fast look-up and mostly correct usage hints and
- code snippets. It does not cover the newest system additions, nor the
- modern "universal" headers format, though.
-
- 1.2) Q: What is the most used Macintosh development system?
-
- A: Out of products on the market, I have no idea; MPW, Think and products
- appear to be used. Lately, CodeWarrior has come out of nowhere and grabbed
- a large share of the market visibility because they have the fastest
- compiler and they generate PowerPC code as well as 68K code. Among
- hobbyists, the Think products from Symantec are most popular because of the
- low price, and steep educational discounts, and, of course, the easily
- approachable interface! However, now that CodeWarrior is available at
- $69-$99 educational price; anything can happen.
-
- The Think C linker only strips dead code on a FILE level basis (and this
- is when you turn on "Smart Linking") The MPW linker (of no specified IQ,
- as someone so eloquently put it :-) strips dead code by the function, as
- does CodeWarrior. That may be part of the reason the Think C linker is
- ten times faster than the MPW linker - but then how do you explain the
- CodeWarrior linker, which links like the MPW linker, but at speeds
- approaching Think C?
-
- In the beginning, the Mac was programmed using Mc68000 assembly or
- Pascal; this was reflected in the Old Inside Mac volumes which only gave
- Pascal-style and assembly-style interfaces to the Mac toolbox. These
- days, Apple tells us to use C or even better C++ for developing new
- applications, as that will speed up the transition to PowerPC and also
- coming cross-platform efforts. (Language Systems have a Pascal for
- PowerPC product now, but I don't know about pricing or quality)
-
- 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.
-
- 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.
-
- Metrowerks have a Pascal and a C and C++ compiler for both 68k and Power
- Macs; the package with the three of them is called "CodeWarrior."
- CodeWarrior is conquering the marketplace rapidly, mostly due to the
- excellent and generous online support. See comp.sys.mac.programmer.
- codewarrior for more information and CodeWarrior-related praise.
-
- Zedcor has FutureBasic, which seems to be very popular.
-
- 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.
- Apple's Dylan enviroment is as far beyond Metrowerks C++ as Metrowerks
- C++ is beyond thick bundles of FORTRAN puch cards.
-
- 1.3) 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 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! Get Involved!
-
- 1.4) Q: Are there any other free Mac development platforms?
-
- A: The best source for information on free compilers/interpreters, such
- as they are 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.5) Q: What's the difference between the MPW, Think and CodeWarrior
- environments?
-
- A: The main difference is that Think and CodeWarrior are integrated
- environments, while MPW provides you with a command-line shell for your
- Mac and tools to use in it. MPW also has a slightly higher systems
- demand and a much slower linker.
-
- The good thing about MPW is that you can write scripts and make files to
- do anything you want in the way you want it. Think doesn't have a
- viable solution to do a build that requires more than one link
- operation, or has more than one destination file. CodeWarrior can be
- AppleScripted to do this.
-
- For the MPW environment, there are three source level debuggers; SADE,
- SourceBug and 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)
-
- 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)
- Stepping through source code and looking at variables is generally
- faster and easier in Think than the MPW debuggers.
-
- 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-saavy.
-
- CodeWarrior is by far the fastest compiler; it can compile to 68k code
- on a Power Macintosh for really fast compiles. Symantec C++ (a k a
- "Think C++") is the most complete C++, containing a somewhat poor
- implementation of templates and no other post-1990 extensions. MPW has
- the most powerful environment, which is inspired directly by Un*x.
-
- Any commercial Mac developer should have CodeWarrior. MPW is an option
- which makes sense if you need to develop code for 68k OpenTransport.
- CodeWarrior includes the non-compiler parts of MPW and MPW-hosted
- Metrowerks compilers/linkers.
-
- 1.6) Q: What is a good low-level debugger for the Mac?
-
- A: MacsBug is freely available for ftp from 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. Macsbug is not native, though PowerPC-dissasembling
- dcmds are available on the Developer CD.
-
- TMON is another debugger which sports a more mac-like interface; it
- provides windows and uses the mouse. It can take as little or much
- memory as you want by excluding or including certain areas of
- functionality. A nice touch is the 6502 disassembler that you can use
- to de-bug the code the IOP processors run on the Mac IIfx and Quadra
- 900/950.
-
- Jasik Designs have 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.
- As a lady put it: "The man wouldn't know a user interface if it bit him
- in the rear." The Debugger is PowerMac native and supports PowerPC
- disassembly.
-
- 1.7) 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.8) 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.
-
- 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.
-
- 1.9) 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. ** Note: there have been some reports of trouble
- with these and PowerMacs.
-
- 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.10) 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>
-
- Icognitive Systems is starting a new magazine called "MacOS
- Development". It's advertised as being for the "professional MacOS
- Developer.'
-
- 1.11) 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.
-
- 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 from nic.switch.ch in the /software/mac/src/Patmos
-
- 1.12) 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.13) Q: CodeWarrior vs. Think/Symantec C++: Which is better?
-
- A: CodeWarrior, assuming you want to develop for PowerMacs. CodeWarrior,
- assuming you want to develop for 68k-based Macs. Metrowerks has publicly
- announced plans for a Mac-hosted x86 cross-compiler (codenamed
- "Icebreaker"), so after next WWDC, you can develop for 486-based PCs.
-
- Note that this applies only to Symantec C++ 7 and below. I haven't yet
- seen 8.0.
-
- 1.14) Q: Can CodeWarrior read Think project files (or, dare I suggest,
- libraries)?
-
- A: No.
-
- 1.15) Q: Why not?
-
- A: Because Metrowerks employs some people who formerly worked at Symantec,
- and they're afraid of possible litigation from Symantec, since they may
- not be able to prove that they didn't get Symantec's proprietary format
- information from those ex-Symantec employees.
-
- 1.16) Q: What are some good books on the subject of learning the Mac
- Toolbox?
-
- A: Any of Dan Parks Sydow's several books on the subject. Recommended
- also is Dave Mark's Mac Programming C Primer. If you don't know C or
- C++, some people recommend Dave Mark's Learn C on the Mac, others don't.
- The problem with the book is that it doesn't teach much (or in fact
- anything) about the art of programming from a Macintosh perspective.
- You receive an introduction to the fundamentals of a particular Mac
- programming enviroment and to some basic C or C++. Much better is the
- combination of the Symantec C++ manual and _Teach Yourself C++_ by Al
- Stevens, an excellent OS-neutral introduction to all of ARM C++, including
- templates and exceptions. For ANSI standard C++ (which is not yet
- available) you'll have to look elsewhere.
-
- 1.17) Q: Source code! I want source code!
-
- 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>
-
- *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 RmveResource 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.
-
- 2.5) 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 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 because it's taken from IBMs AIX. No limitations
- there.
-
- *3* User interaction and You
-
- 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!
-
- 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 15.2.
-
- 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).
-
- 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 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*
- 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 ] ) {
- 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 ;
- parent -> name [ 0 ] = 0 ;
- }
- return err ;
- }
- *end*
-
- *code*
- OSErr
- GetFullPathHandle ( FSSpec * fss , Handle * h ) {
-
- Handle tempH = NULL ;
- short err ;
- FSSpec fs = * fss ;
-
- 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 ;
- }
- GetVolName ( fs . vRefNum , fs . name ) ;
- 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 ) ; // Remove colon }
- 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.
-
- 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.
-
- 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 looking 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? One page of code; there is also 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 always pay Marco P. to finish up WASTE 1.1 with it's
- embedded objects implementation (want quicktime movies that play and
- flow with the text?)
-
-
- 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 priovides 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.
-
- 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 and Linking
-
- 9.1) Q: How do I do code resources/extensions/external functions, much
- like HyperCard XCMDs only for my 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).
-
- *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) 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>
-
- - C-Index Pro is an engine that comes with source, does tables and indexes
- in one compound file. <triosystems@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.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 Public Domain
- Programming FAQ sent you!
-
- *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
-
- [let me know if I've forgotten you]
-
- Denis Birnie
- Scott Bronson <urge@mcl.mcl.ucsb.edu>
- Tim Converse <converse@cs.uchicago.edu>
- Julian Harris
- Bruce Hoult <Bruce@hoult.actrix.gen.nz>
- Peter Jensen <pjensen@netcom.com>
- Jonathan Kimmitt <jrrk@camcon.co.uk>
- Matthias Neeracher <neeri@iis.ee.ethz.ch>
- David P. Oster <oster@netcom.com>
- Pete Resnick <resnick@uiuc.edu>
- eric slosser <slosser@apple.com>
- Chris Thomas <thunderone@delphi.com>
- Jon W"atte <h+@nada.kth.se>
- Rick Zaccone <zaccone@bucknell.edu>
-
-
-
-
- --
- -- Jon W{tte, h+@nada.kth.se, Mac Software Engineer Deluxe --
- "Psychotherapist" - "Phycho-The-Rapist"
- Pure coincidence? You decide!
-