home *** CD-ROM | disk | FTP | other *** search
/ ftp.pasteur.org/FAQ/ / ftp-pasteur-org-FAQ.zip / FAQ / macintosh / programming-faq < prev    next >
Text File  |  1995-07-05  |  92KB  |  2,203 lines

  1. Path: senator-bedfellow.mit.edu!bloom-beacon.mit.edu!hookup!swrinde!dish.news.pipex.net!pipex!edi.news.pipex.net!pipex!sunic!sunic.sunet.se!news.kth.se!hemul.nada.kth.se!d88-jwa
  2. From: d88-jwa@hemul.nada.kth.se (Jon WΣtte)
  3. Newsgroups: comp.sys.mac.programmer.misc,comp.sys.mac.programmer.info,comp.answers,news.answers
  4. Subject: The Mac Programming FAQ Answer sheet. [READ ME!]
  5. Followup-To: comp.sys.mac.programmer.misc
  6. Date: 5 Jul 1995 02:19:16 GMT
  7. Lines: 2186
  8. Approved: news-answers-request@MIT.Edu
  9. Expires: 14 Jul 1995 00:00:00 GMT
  10. Message-ID: <3tcsr4$p5e@news.kth.se>
  11. NNTP-Posting-Host: hemul.nada.kth.se
  12. Mime-Version: 1.0
  13. Content-Type: text/plain; charset=iso-8859-1
  14. Content-Transfer-Encoding: 8bit
  15. Xref: senator-bedfellow.mit.edu comp.sys.mac.programmer.misc:7624 comp.sys.mac.programmer.info:237 comp.answers:12870 news.answers:47721
  16.  
  17. Archive-name: macintosh/programming-faq
  18.  
  19. Mac Programming Frequently Asked Questions Answer Sheet
  20. Last update: 10 May 95 - sharp dressed FAQ
  21.  
  22. Please download a copy of this answer sheet and search it before you 
  23. post to the 'net, to help reduce bandwidth.
  24.  
  25. Please send all correspondence regarding content directly to the current 
  26. caretaker and content editor, Chris Thomas, <thunderone@delphi.com>.  
  27. All submissions sent will be considered to be in the public domain 
  28. unless stated otherwise (in which case they will not be included in this 
  29. FAQ sheet).  When writing, be sure that you include something 
  30. appropriate in the subject line.  I'm now automatically deleting mail 
  31. with blank or whitespace subjects unread due to the growing nasty 
  32. practice of sending junk email without a subject.  The idea, apparently, 
  33. is to be cute and get you to read the mail without deleting it.  This 
  34. sheet was started and is distributed by Jon Watte, whom you may reach as 
  35. <h+@austin.metrowerks.com>.
  36.  
  37. This sheet is currently archived on nada.kth.se where you can reach it 
  38. using afs as /afs/nada.kth.se/public/ftp/pub/hacks/mac-faq/CSMP_PD_FAQ 
  39. or using anonymous FTP as pub/hacks/mac-faq/CSMP_PD_FAQ You can also 
  40. find it on rtfm.mit.edu unedr the name macintosh/programming-faq.  WWW 
  41. version is available as <http://www.nada.kth.se/~d88-jwa/mac-faq.html>.
  42.  
  43. No FAQ can substitute for real documentation (some of which is 
  44. mentioned in this FAQ) If you ask a question in comp.sys.mac.programmer 
  45. which has a good answer in one of the important sources, you will probably 
  46. not get an answer.  (Inside Macintosh, Macintosh Technical Notes being 
  47. important sources).
  48.  
  49. There is NO or VERY LIMITED error checking in the code examples, FOR 
  50. BREVITY ONLY.  You should make sure you ALWAYS check ALL return codes, 
  51. and handle any that you are not prepared to deal with appropriately.  
  52. Needless to say, do not use the code as is.
  53.  
  54. Exciting new stuff:  More general dev tools update.  See especially 
  55. question 1.2.  List Manager replacements.  The usual tweaking.
  56.  
  57. Topics:
  58. [search for *number* to find a topic quickly]
  59. [topics changed since last FAQ are marked with "+", new topics with ">"]
  60.  
  61.  1. +Development Tools
  62.      getting started, tool-specific issues
  63.  2. Memory
  64.      handles, large arrays, resource handles
  65.  3. User Interfacing
  66.      menus, windows, events, multitasking
  67.  4. Files
  68.      Mac fopen, wdrefnums, getting full pathnames
  69.  5. Imaging
  70.      QuickDraw and the means to avoid it
  71.  6. Text
  72.      Text editing packages, string conversion
  73.  7. Communications and Networking
  74.      Serial ports, TCP/IP, sockets
  75.  8. Interapplication Communication
  76.      AppleEvents, OSA, Scripting, and You
  77.  9. Dynamic Linking & Code Resources
  78.      the dynamics of code resources & trap patches
  79. 10. Compatibility
  80.      gestalt & glue
  81. 11. Optional System Software
  82.    11.1. QuickTime
  83.        codec details and the lack thereof
  84. 12. Third-Party Solutions
  85.    12.1. Databases
  86.        client/server solutions for the masses
  87.    12.2. >Circumventing Toolbox Limitations
  88.        foul baggage begone- List Manager replacements
  89. 13. Dessert
  90.      yummies the Macintosh Way
  91. 14. Contributors
  92.      whodunnit
  93.  
  94. *1* Development and debugging tools for the Macintosh 
  95.  
  96. 1.1) Q: What do I need to start writing Macintosh software? 
  97.  
  98. A: A Mac, a lot of time, and a few hundred $.  Although you can develop 
  99. software on a Classic-type machine, it is not to be attempted by the 
  100. weak of heart or stressed of time.  If you're doing paid work and/or 
  101. work for a company, a Quadra-class machine is a must; remember that your 
  102. time costs your employer much more than just your salary.  A PowerMac is 
  103. highly preferable.  16 MB is a minimum to run at all comfortably (40 MB 
  104. recommended), and Virtual Memory (including RamDoubler, unfortunately) 
  105. is not suited for development work.  Similarly, if you don't have at 
  106. least 80 MB free on your hard disk you need to buy more space.  You will 
  107. also need a CD-ROM drive.
  108.  
  109. You need a development system such as CodeWarrior, MPW Pro, Symantec C++ 
  110. 8.0 or Prograph, you need at least some of the New Inside Mac books 
  111. (Toolbox Essentials, Files, Memory come to mind) and a good entry-level 
  112. third-party book may help.
  113.  
  114. Once you are up to speed on the general layout of the Mac and its 
  115. toolboxes, you should call APDA and order the monthly developer mailing, 
  116. which will give you a CD chock full of documentation, utilities and 
  117. system software once a month.  You will also, obviously, need a CD 
  118. player; Apple's own CD600 is a very good buy at the time of this 
  119. writing.  If you don't have the dough for the monthly mailing 
  120. ($250/year) you can order a _develop_ subscription; this quarterly 
  121. magazine ($30-$50/year) comes with a CD containing most Inside Mac 
  122. documentation.  Another good product to order is the MacOS SDK, which 
  123. for $99 gives you a CD with every API in existence up to and including 
  124. the 7.5 Mac Toolbox additions.  It's somewhat redundant if you already 
  125. have the Developer CD subscription.  <apda@appplelink.apple.com> Apple's 
  126. Developer Web has almost all of the contents of the Developer CD online.  
  127. <http://www.info.apple.com/dev>
  128.  
  129. If you don't know how to program, go learn your language of choice 
  130. BEFORE attempting a "real" Mac application.  Programming is a discipline 
  131. often requiring different thought processes than your normal day job.  A 
  132. beginning book, like Lippman: The C++ Primer, one of the Teach Yourself 
  133. C++ books, or the primers available on the CodeWarrior CD, might help.
  134.  
  135. An indispensable Mac programming tool is the Macintosh Programmer's 
  136. Toolbox Reference (MPTA), an up-to-date hypertext reference guide 
  137. containing reference material on the New Inside Mac-documented portions 
  138. of the Toolbox with lightning-fast look-up and mostly correct usage 
  139. hints and code snippets.  MPTA can be found on the Developer CD, and is 
  140. also offered on a seperate $99 CD.  <apda@applelink.apple.com>
  141.  
  142. Think Reference version 2.0.1, precursor to MPTA, contains reference 
  143. material on many parts of the Mac toolbox with lightning-fast look-up 
  144. and mostly correct usage hints and code snippets.  While it does not 
  145. cover any post-System 7 system additions, nor the modern "universal" 
  146. headers format, it does include information on the standard C/C++ 
  147. libraries.  Available wherever fine Symantec products are sold - 
  148. <apda@applelink.apple.com> for one.
  149.  
  150. 1.2) Q: What is the most used Macintosh development system? 
  151.  
  152. A: Currently, the three most widely used are CodeWarrior (CW), MPW, and 
  153. Symantec C++, probably in that order, though I don't have any 
  154. statistics.  The latest version of any one of these is adequate for Mac 
  155. development.
  156.  
  157. CodeWarrior: In early 1994, CodeWarrior came out of nowhere and grabbed 
  158. a large share of the market visibility because they had the fastest 
  159. compiler and they generated PowerPC code as well as 68K code.  Today, 
  160. CodeWarrior has the smoothest development environment and most complete 
  161. C++ implementation, supporting both templates and exceptions.  CW/6 
  162. includes C, C++, and Object Pascal support, and can generate x86 
  163. binaries.  Among hobbyists, CW seems to be the most popular because of 
  164. it's low price, ultra-fast compile time, and support that no other 
  165. company on the planet can match.  See comp.sys.mac.programmer.codewarrior
  166. for more information and CodeWarrior-related praise.  Contact 
  167. <sales@metrowerks.com>.
  168.  
  169. MPW: The grandaddy of all Mac development environments, descended from 
  170. the original Mac development environment based on a Lisa.  MPW is an 
  171. extremely flexible, powerful, Unix-like command line environment with 
  172. makefile, multiple windows and split-pane support.  Many development 
  173. tools are MPW-based.  MPW Pro comes with C, C++, Pascal, assemblers for 
  174. both 68k and PowerMac, various other useful tools, and the C++-based 
  175. framework MacApp for a reasonable price.  MPW has in the past been 
  176. extremely slow, but shows signs of redemption.  Contact 
  177. <apda@applelink.apple.com>.
  178.  
  179. Symantec C++: This is the eighth-generation descendant of the C
  180. environment favored by Mac developers for over five years.  Symantec C++ 
  181. 8.0 is a complete, scriptable, modular development environment including 
  182. C, C++, and soon, a PowerPC assembler.  The C++ implementation supports 
  183. templates.  A development version of a PowerPC C++ compiler supporting 
  184. exceptions and RTTI is available at Symantec's devtools site.  SC++ 8.0 
  185. doesn't at this time support 68k Mac development.  For that purpose, 
  186. you're required to use the old, decrepit TPM development environment, 
  187. which is included.  Contact <sales@devtools.symantec.com>.
  188.  
  189. There are also at least two Fortran compilers, at least three SmallTalk 
  190. implementations (ObjectWorks, SmallTalk/V and SmallTalkAgents) and 
  191. others.  There are ways of stripping SmallTalk apps so they're smaller 
  192. and faster as standalone apps than in the environment.
  193.  
  194. Languge Systems has Object Pascal and Fortran for PowerMac.  Absoft has 
  195. Fortran and C++ for PowerMac.  These all require MPW.
  196.  
  197. There's also a world-class LISP/CLOS implementation from Apple called 
  198. Macintosh Common Lisp.  Recently, Apple announced that DigiTool has 
  199. licensed MCL with the intent (among other things) to provide a PowerMac 
  200. version and other updates.
  201.  
  202. Zedcor has FutureBasic, which seems to be a very popular...  It also 
  203. seems to be the only well-supported implementation of BASIC on 
  204. Macintosh.
  205.  
  206. CSI has MacForth, of which I only know the name and someone who says 
  207. it's pretty good.
  208.  
  209. There is another good Common Lisp implementation: Procyon Common Lisp.  
  210. I don't know if it is actively supported, but Procyon CL is also 
  211. available for DOS, OS/2 and Windows (as Allegro CL/PC) and actively 
  212. developed.
  213.  
  214. A new possible up-and-coming languge is Apple's Dylan, which is 
  215. something of a cross between BASIC, Pascal, and C.  C-based code can be 
  216. used directly from Dylan, but Dylan can't yet be used directly from C.  
  217. The Apple Dylan environment is rumored to be as far beyond MPW as MPW is 
  218. beyond thick bundles of FORTRAN punch cards.
  219.  
  220. 1.3) Q: Okay, which is the most used Mac programming languge?
  221.  
  222. A: The existing Macintosh code base is mostly C, with C++ second, and 
  223. Pascal finding it's niche in third.  Few people are writing mainstream 
  224. software in Pascal anymore, probably because (a) it's rather hard to 
  225. move to non-Mac platforms (b) Pascal is only rarely being taught past 
  226. the first year in Computer Science.
  227.  
  228. 1.4) Q: Where do I find a free/share/copyleftware C compiler for the Mac? 
  229. Is there a GCC for the mac? What about the FSF boycott of Apple products?
  230.  
  231. A: There is no really good solution for a "for-free" C development 
  232. system for the Mac.  GCC has been ported, but requires the MPW shell and 
  233. MPW assembler to run; these have to be bought from APDA.  There is a 
  234. standalone port of GCC 1.37 on nic.switch.ch:software/mac/src/think_c.  
  235.  
  236. gcc-1.37r14 V1.1 standalone is available for ftp at nic.switch.ch: 
  237. software/mac/src/think_c.
  238.  
  239. A not-entirely-stable port of GCC 2.3.3 to MPW is available for ftp at 
  240. atg.apple.com [anyone know the directory?].  A much more solid port of 
  241. GCC 1.37 is available for MPW as well.
  242.  
  243. Stan Shebs <shebs@cygnus.com>, the driving force behind all of the MPW 
  244. GCC ports, is working on a new port of GCC 2.5.8.
  245.  
  246. For those whose main interest is in developing only text-based C/C++ 
  247. programs, using GCC under MacMiNT might be appropriate.  MacMiNT is a 
  248. UNIX like operating system ported from the Atari ST which supports many 
  249. freely available UNIX utilities like GCC, GDB, make, tcsh, byacc, perl, 
  250. and more.  MacMiNT stuff can be found at nic.switch.ch in 
  251. 'software/mac/src/macmint'.
  252.  
  253. The FSF/LPF boycott of Apple products is over as of January 1995, which 
  254. means they will now incorporate changes made for Macintosh into their 
  255. main code base, if such changes are easily incorporated, and they 
  256. won't be any more antagonistic to Mac programmers than they would be 
  257. to any other micro-to-workstation-class programmers.
  258.  
  259. So what are you waiting for? Go out and port something from GNU! Send in 
  260. the changes!  We still lack decent free development tools!
  261.  
  262. 1.5) Q: Are there any other free Mac development platforms? 
  263.  
  264. A: The best source for information on free compilers/interpreters is the 
  265. Free Compilers FAQ which is written by Brian Connors 
  266. <connorbd@cleo.bc.edu>.  Watch for it in c.s.m.p.info.
  267.  
  268. 1.6) Q: What's the difference between the MPW, Think and CodeWarrior 
  269. environments?
  270.  
  271. A: As of CodeWarrior/6, MPW 3.3, and Symantec C++ 8.0.1 (SC++), 
  272. CodeWarrior will allow faster turnaround times, MPW will provide the 
  273. most flexibility and overall power, and Symantec C++ has the edge with 
  274. regard to helpful project browsing features.
  275.  
  276. CW C++ supports templates and exceptions, Symantec C++ supports only 
  277. templates, MPW's new compilers are based on Symantec C++.
  278.  
  279. SC++ 8 doesn't generate 68k code, while pre-CW/6 CodeWarrior requires 
  280. you to use seperate (virtually identical) environments, and builds are 
  281. controlled from a Makefile in MPW, of course.
  282.  
  283. All three need much hard disk space.  SC++ requires the most RAM.  MPW 
  284. requires the most disk space.
  285.  
  286. MPW is the slowest, followed distantly by SC++, which is followed 
  287. closely by CodeWarrior.
  288.  
  289. The best thing about MPW is that you can write scripts and make files to 
  290. do anything you want in the way you want it.  SC++ and CodeWarrior can 
  291. be AppleScripted to do builds that require more than one link operation, 
  292. but the process is more involved, and CW doesn't currently support 
  293. scripting in full.  SC++ 8 can do builds which require more than one 
  294. link operation.
  295.  
  296. For the MPW and CodeWarrior environments, there are four source level 
  297. debuggers; Metrowerks, SADE, SourceBug, Voodoo Monkey.  The latter is an 
  298. experimental debugger with support for threads debugging; the middle is 
  299. bundled with MPW while SADE has to be bought separately (but is fully 
  300. scriptable in its own scripting language).  Metrowerks Debugger is 
  301. included with CodeWarrior.
  302.  
  303. The Think environments have their own integrated debuggers; the Think 
  304. Pascal one has a lot of useful features while the Think C/C++ one is a 
  305. little more basic (but is gaining in functionality with each release).
  306.  
  307. Metrowerks has their own debugger which works like the MPW debuggers; i e 
  308. it runs the application standalone and pokes at it from the outside, 
  309. while the Think debuggers run the application "wrapped" in a special 
  310. environment, making for some subtle interferences with your heap (which 
  311. you usually don't notice).  The Metrowerks Debugger is Thread 
  312. Manager-savvy on the 68k side.
  313.  
  314. BOTTOM LINE:
  315.  
  316. If you're developing for both Power and regular 68k Macs, you need 
  317. CodeWarrior.  MPW is an option which makes sense if you need to develop 
  318. code for non-CFM OpenTransport or if you have a ridiculously large 
  319. number of independent code modules to compile, or if you're a Unix 
  320. person.  CodeWarrior, in addition to it's own integrated environment, 
  321. includes the non-compiler parts of MPW and MPW-hosted Metrowerks 
  322. compilers/linkers.  SC++ is an option only for PowerMac development.
  323.  
  324. 1.7) Q: What is a good low-level debugger for the Mac? 
  325.  
  326. A: MacsBug is freely available for ftp from <ftp://ftp.apple.com>; log 
  327. in as user anonymous and give your FULL e-mail address as password.  
  328. MacsBug is your basic monitor-type debugger that takes a few hundred Ks 
  329. of memory, and lets you break, step, disassemble, look at the stack etc 
  330. of most anything running on your Mac.  Since it's free (it's also on the 
  331. developer CDs) and provides most of the functionality you need, this is 
  332. a popular choice.  As of 6.5d10, Macsbug supports PowerPC debugging.
  333.  
  334. Jasik Designs has a debugger called The Debugger which can do both low- 
  335. and high-level debugging, with or without source and for all types of 
  336. code, application, code resources, everything.  This is the debugger of 
  337. choice for many large developers because of its high power and many 
  338. features not found anywhere else.  However; newcomers beware! This is 
  339. the Lamborghini of debuggers; if you know how to drive it, it is the 
  340. fastest way from A to B; if you don't, you'll just end up in the ditch.  
  341. The Debugger is PowerMac native and supports PowerPC disassembly.  It 
  342. includes an excellent code coverage tool and MacNosy, a general 
  343. disassembler.  Support is direct from the author and generally great.
  344. <macnosy@jasik.com>
  345.  
  346. 1.8) Q: Are there any visual developments environments for the 
  347. Mac (comparable to Visual C++)?
  348.  
  349. A: There is no Visual C++ as such.  However, there is a C++ parser/editor 
  350. called ObjectMaster which provides good browsing and editing capabilities 
  351. if you already have a C++ compiler.  A demo is available on the CodeWarrior 
  352. CD.  Think C++ comes with a browser built-in, and you can edit 
  353. dialogs/windows using plain old ResEdit, even for your custom view types.
  354.  
  355. Symantec C++ 7.0 also bundles a view editor/code generator called Visual 
  356. Architect; it is fairly complete and has a good level of integration 
  357. into the Think Project Manager.
  358.  
  359. AppMaker is a GUI builder/code generator.  Granted, it's not as nice as 
  360. VC++, but it's quite a product in any case.
  361.  
  362. MarksMan version 3.0 has totally revised TCL templates, and now 
  363. generates well-thought-out TCL code.  It can also generate ANSI C code 
  364. etc.
  365.  
  366. Also, Neuron Data has their UI tool called Open Interface, which is 
  367. better than VC++ and creates code portable across 35 platforms.  
  368. Unfortunately it's $2500 per developer per platform.  There's also two 
  369. other cross-platform products called XVT and Galaxy, the former has 
  370. gotten flak on UseNet while the latter reportedly is the premier 
  371. cross-platform application builder framework; with everything from 
  372. styled text to network support.
  373.  
  374. There is a fully visual, dynamic, object oriented data-flow-driven
  375. programming language for the Mac called Prograph CPX.  It features a
  376. full-featured class library, a powerful, user-extensible GUI Builder, full
  377. access to the entire Mac toolbox, a database engine, high-level interfaces
  378. to SQL, Oracle, etc.  But the coolest thing about Prograph is its
  379. interpretative debugger, fully integrated with the visual code editor,
  380. which lets you write your code _while it's running_.  Execution
  381. automatically rolls back to where changes you make have relevance.  A
  382. PowerMac-native compiler and a Windows version are expected in '95.  A
  383. complete demo version is available from <sales@prograph.com>.  Cost is 
  384. $695 ($395 for students).
  385.  
  386. SmalltalkAgents comes with a GUI builder, which lets you draw your
  387. interface, and then outputs the code for you.
  388.  
  389. If you'd rather do Common Lisp, Macintosh Common Lisp offers a Common 
  390. Lisp Object System with support for most Mac interface items; you can 
  391. edit code while it is running and build stand-alone applications.
  392.  
  393. However, all of these tools generate rather larger binaries with larger 
  394. system demands than a program written in C.  On the other hand; C++ 
  395. programs require more memory and disk space than programs written in 
  396. assembly.  It's a trade-off, and I believe this type of tools is the 
  397. wave of the near future.
  398.  
  399. 1.9) Q: What class libraries are there for the Mac? 
  400.  
  401. A: Apart from the libraries mentioned above, there are three contenders: 
  402. MacApp, TCL, and PowerPlant.  "Bedrock" will never be released as a 
  403. product, although parts of it surface in TCL 2.0 and other parts will be 
  404. the base for the OpenDoc Parts Framework.
  405.  
  406. MacApp is a heavy-duty class library that has tons of features and a 
  407. steep learning curve; it runs under MPW with Pascal or C++, and also 
  408. under Think Pascal 4.0 A major application written in MacApp is 
  409. PhotoShop.
  410.  
  411. TCL stands for Think Class Library and comes with Think Pascal, C or 
  412. C++.  It is a smaller library that still fills most peoples needs; since 
  413. Think C implements a subset of C++ (the most important OO concepts such 
  414. as virtual functions and inheritance) and the TCL is carefully written 
  415. not to take advantage of any C++ features not in Think C, you can use it 
  416. with Think C.  A major application written in TCL is Lotus 1-2-3.  (TCL 
  417. 1.1.3) Starting with Symantec C++ 7.0, Think Class Library 2.0 using 
  418. templates and "real" C++ objects is shipping.
  419.  
  420. The C++ Standard Template Library (STL) compiles under Symantec C++ 
  421. and CodeWarrior, and versions are available for both.
  422.  
  423. PowerPlant is the Metrowerks CodeWarrior offering; it's written by the 
  424. guy who designed the Think Class Library, but it has a lot of 
  425. differences from the original TCL; for one, it's not a monolithic one 
  426. base class framework.  On the other hand, it has some catching up to do 
  427. before it reaches the level of MacApp.  It is gaining quite fast on TCL, 
  428. but isn't all there yet.  It has the most complete support for 
  429. AppleEvents & scripting & drag & drop other modern features.
  430.  
  431. 1.10) Q: How should I debug and test my software? 
  432.  
  433. A: Get ahold of, and install, the extensions DoubleTrouble, 
  434. DisposeResource and EvenBetterBusError.  They will catch 80% of any 
  435. memory related bugs you may have, including many bugs that follow NULL 
  436. handles or pointers.  (Jasik's Debugger (see above) obviates the need 
  437. for these.)
  438.  
  439. A low-level debugger is required, and while you install it, install the 
  440. "leaks" dcmd which will help you catch memory leaks in your application.  
  441. All of these tools are available from <ftp.apple.com>.
  442.  
  443. 1.11) Q: Are there any good Mac programming magazines?
  444.  
  445. A: One Mac programming magazine I know of is MacTech Magazine (formerly 
  446. MacTutor).  It covers a variety of Mac programming topics on various 
  447. levels.  Operating independently from Apple, it has a lot of stuff for 
  448. the beginning Mac programmer, as well as occasional nuggets for the more 
  449. experienced of us.  <custservice@xplain.com>
  450.  
  451. Another VERY GOOD Magazine is _develop_ which is put out by Apple four 
  452. times a year; it comes with a CD containing code for all articles ever 
  453. published in _develop_, and a lot of documentation and system software 
  454. freebies as well.  $30/year in the US.  <dev.subs@applelink.apple.com>
  455.  
  456. 1.12) Q: What about protected memory? I'm sick and tired of re-booting 
  457. when my application crashes.
  458.  
  459. A: Write better software! 
  460.  
  461. Or install The Debugger from Jasik Designs, which can provide your 
  462. application with write-protection of critical parts of memory, if you have 
  463. a 68030-equipped Mac.
  464.  
  465. Making the Mac OS memory-protected is tricky, because applications expect 
  466. to be able to write to low memory, the system heap, temporary memory, 
  467. window lists, and even each other's heaps in some interapplication 
  468. communication solutions that date back to before AppleEvents and the PPC 
  469. Toolbox.  To add to the burden, Apple's own software tends to be the 
  470. worst offender in these cases.
  471.  
  472. But fear not, Mac fans! Jonathan Kimmitt has written Patmos, the 
  473. "Protected address translation mode operating system".  It is an 
  474. application that brings the advantages of protected mode programs to 
  475. your Quadra class Macintosh by the simple expedient of taking over the 
  476. memory management unit of the 68040 in a very simple kernel (<100K in 
  477. size), we immediately gain compatibility with the BSD unix program 
  478. environment.  The advantages of this are as follows:
  479.  
  480. (a) You can run certain programs (such as /bin/sh) designed for MacBSD
  481. (b) You can compile almost all GNU software including C and C++ without.
  482. modifying the source code in any way
  483. (c) All programs run with a flat 32-meg address space, with no worries
  484. about 32K segments or the other mac paraphernalia.
  485. (d) The majority of program bugs can be caught cleanly without crashing
  486.  your mac
  487. (e) All your files are shared between Patmos and MacOS so you can edit 
  488. using your favourite mac editor, then immediately compile in Patmos 
  489. without having to reboot or copy files around.
  490.  
  491. The downside is that not all macs use the memory management unit in the 
  492. same way, or even have the same kind of MMU, so Patmos may not run on 
  493. your particular mac model.  However, since the kernel source code is 
  494. very small, the task of adapting it to a new environment is very simple, 
  495. and once achieved, all application programs running in user mode are 
  496. enabled to run without even recompiling.
  497.  
  498. <ftp://nic.switch.ch in /software/mac/src/patmos>
  499.  
  500. 1.13) Q: I have this library written in (Think) Pascal that I want to use 
  501. from Think C/Symantec C, but I get link errors/don't know how to do it.  
  502. What should I do?
  503.  
  504. A: Start by writing a .h file describing the interface.  Remember to 
  505. declare the Pascal functions "pascal".  Build a library with Think Pascal 
  506. and convert it with oConv.
  507.  
  508. Do you get link errors on symbols defined in your Pascal lib? Check the 
  509. capitalisation used.
  510.  
  511. Do you get errors on symbols like LMUL and LDIV? Those functions are 
  512. defined in the Think Pascal library Runtime.lib or uRuntime.lib.  Include 
  513. uRuntime.lib and try again.
  514.  
  515. Do you get link errors on standard symbols like thePort? This is due to 
  516. bad capitalization in Symantec's libs.  Run oConv with .v checked.  This 
  517. will create a TEXT file with a .v extension.  Open that with a text 
  518. editor and correct the capitalization.  Run oConv again, with .v checked 
  519. this time too.
  520.  
  521. Do you still get errors on standard symbols? Are you using Think 
  522. C/Symantec C++ version 6 or higher? Then you must open the library (after 
  523. converting it) from Think C version 5, and remove the unit named 
  524. %_TOOLBOX.  (If I'm not mistaken, this is the toolbox init unit, which 
  525. you won't need anyway.)
  526.  
  527. 1.14) Q: CodeWarrior vs. Think/Symantec C++:  Which is better?
  528.  
  529. A:  See the above discussion on CodeWarrior, Think, and MPW for a full 
  530. understanding of the issues involved.
  531.  
  532. 1.15) Q: Can CodeWarrior read Think libraries?
  533.  
  534. A: Yes, in a way.  Here are the steps required.
  535.  
  536. 1) Secure a copy of Think Pascal and a machine that can run it
  537. 2) Import the Think C library into Think Pascal
  538. 3) Build a Think Pascal library (in MPW format)
  539. 4) Import MPW format library into CodeWarrior
  540.  
  541. 1.16) Q: What are some good books on the subject of learning the Mac 
  542. Toolbox?
  543.  
  544. A: Any of Dan Parks Sydow's numerous books on the subject.  Recommended 
  545. also is Dave Mark's _Ultimate Mac Programming_ (a Macworld book, for 
  546. some odd reason).  Stay away from Dave Mark's _Learn C on the Mac_ and 
  547. _Learn C++ on the Mac_.
  548.  
  549. See also Nick DeMello's books review, posted in c.s.m.p.info from time 
  550. to time.
  551.  
  552. 1.17) Q:  Source code!  I want source code!  Where can I find some?
  553.  
  554. A: Celestin Company, Inc. sells the Apprentice 2 CD-ROM.  Apprentice 
  555. contains over 600 megabytes of programmer utilities and up-to-date 
  556. source code in CodeWarrior, Symantec, and MPW projects for C, C++, and 
  557. Pascal.  <ftp://ftp.teleport.com/vendors/cci/apprentice/apprentice.hqx>
  558. for an index and info.  <celestin@olympus.net>
  559.  
  560. Also, the alt.sources.mac archive at <ftp://ftpbio.bgsu.edu> contains a 
  561. lot of misc. source code and snippets not found elsewhere.
  562.  
  563. <ftp://nic.switch.ch> is another good source for unique source code.
  564.  
  565. Info-mac is a good source for source, info-mac/dev/src.
  566.  
  567. 1.18) Q: I'm trying to use a largish array in Think C, but get a "code 
  568. overflow" error.  This is valid C, why doesn't it work?
  569.  
  570. A: The ANSI standard does not guarantee that any structure larger than 
  571. 32767 bytes be correctly handled.  Because of historical constraints, 
  572. the Mac memory model is built around several small blocks of size 32K or 
  573. less; these are used both for code and global/static data.  If you want 
  574. to use more code or data, you have to turn on "far code" or "far data" - 
  575. you still will not get around the restriction of 32K code or data per 
  576. compiled file, though.
  577.  
  578. This is one area where CodeWarrior's 68k support shines; it works around 
  579. most such limitations and it doesn't cost much in performance either!
  580.  
  581. As opposed to, say, DOS or Windows, however, you can allocate as much 
  582. memory as you want (and there is in the machine) and step through it 
  583. using ordinary pointers; it's just that global and static data space is 
  584. addressed off the A5 register using a 16bit displacement addressing mode 
  585. in the 68000 processor.
  586.  
  587. On the PowerPC, everything is 32bit from the start; that runtime model 
  588. is much more like UNIX.  The horizon is the limit.
  589.  
  590. *2* Memory
  591.  
  592. 2.1) Q: What is a handle? 
  593.  
  594. A: A handle is a pointer to a pointer to something.  However, it is more 
  595. than that; creating a handle by taking the address of one of your own 
  596. pointers does NOT create a Handle; the Memory Manager will only deal 
  597. properly with Handles that are created using NewHandle or something that 
  598. calls it (such as NewRgn or GetResource).
  599.  
  600. 2.2) Q: When do I have to lock a Handle? 
  601.  
  602. A: The contents of a Handle may move, and when it does, the pointer your 
  603. handle is pointing to is changed to point to the new address so your 
  604. handle is always valid.  The toolbox may call the memory manager to 
  605. allocate more memory pretty much anytime you call it (the toolbox) and 
  606. when memory is allocated, your handle may move in memory.  Don't 
  607. dereference a handle into a pointer (or take the address of a field in a 
  608. record a handle is double-pointing to) and then call the toolbox and 
  609. expect the pointer to still be valid.  The only way to ensure that the 
  610. pointer will still be valid is to call HLock on the handle to lock it.
  611.  
  612. Use HGetState and HSetState to save & restore the "locked" state of a 
  613. handle when you lock it.
  614.  
  615. 2.3) Q: How do I dispose of Handles? 
  616.  
  617. A: DisposeHandle (formerly called DisposHandle) once and ONLY once will 
  618. do the trick.  Trying to dispose of an already disposed Handle is an 
  619. error.  DoubleTrouble (see above) will catch such bugs when they do 
  620. occur.
  621.  
  622. 2.4) Q: What about resources? 
  623.  
  624. A: Calling GetResource returns NULL if the resource is not found or 
  625. there is not enough memory, else it returns a handle to the resource.  
  626. This handle may be moved or locked like any other handle, but DO NOT 
  627. call DisposeHandle to get rid of a resource handle - call 
  628. ReleaseResource.  DisposeResource (see above) will catch this kind of 
  629. bug.
  630.  
  631. Remember that AddResource makes a resource handle out of an ordinary 
  632. handle, and RemoveResource or DetachResource makes an ordinary handle 
  633. out of a resource handle.  You cannot call AddResource with a resource 
  634. handle; you have to DetachResource it first.
  635.  
  636. Resource handles are automagically disposed when the resource file they 
  637. belong to is closed.
  638.  
  639. *3* User / Machine interaction
  640.  
  641. 3.1) Q: How do I read the modifier keys of the keyboard? 
  642.  
  643. A: Just call EventAvail and check the event.modifiers field. 
  644. Only works when you are in the foreground. You can also use 
  645. GetKeys(), or (as a last resort) check the lo-mem global KeyMap 
  646. directly. 
  647.  
  648. 3.2) Q: How do I move the mouse cursor to a specific position?
  649.  
  650. A: Wait! Don't do it! There has to be a better way!
  651.  
  652. If you feel you HAVE to do it (for a game or VERY special simulation 
  653. situation) you can use the Cursor Device Manager documented in the tech 
  654. notes on <ftp.apple.com>.  If that manager is not installed, as it's not 
  655. on older Macs, you can use the following code:
  656.  
  657. You need to have some low-memory globals defined.  they may be defined 
  658. in SysEqu.h.
  659.  
  660. #define MTemp 0x828
  661. #define RawMouse 0x82c
  662. #define CrsrNewCouple 0x8ce
  663.  
  664. Note that CrsrNewCouple is actually a combination of two globals, just 
  665. to make our life slightly easier.
  666.  
  667. The code I use to move the mouse is:
  668.  
  669. *code*
  670. void
  671. MoveMouseTo ( Point where ) {
  672.  
  673.     HideCursor ( ) ;
  674.     * ( Point * ) RawMouse = where ;
  675.     * ( Point * ) MTemp = where ;
  676.     * ( short * ) CrsrNewCouple = -1 ;
  677.     ShowCursor ( ) ;
  678. }
  679. *end*
  680.  
  681. You need to hit a couple more global variables if you want this to work 
  682. properly in a multiple-monitor system, but i forget what they are 
  683. offhand.  poke through SysEqu.h, and you should be able to figure it out 
  684. without a problem.
  685.  
  686. On the PowerPC, these lo-mem globals may not be available for native 
  687. applications; however, all Power Macintoshes implement the Cursor Device 
  688. Manager.  All Macs made after March '93 (including Centris 650 and 610) 
  689. implement the Cursor Device Manager, in fact.
  690.  
  691. There is also a file on nada.kth.se:pub/hacks/mac-faq/MoveMouse.c which 
  692. shows how to use the Cursor Device Manager, written by an excellent 
  693. Apple engineer.  Grab!
  694.  
  695. Careful, version 1.0 of the Universal Header "CursorDevices.h" file was 
  696. completely incorrect.  Use 2.0a3 or later.
  697.  
  698. 3.3) Q: My menus don't show up in the menu bar
  699.  
  700. A: If your menus are hiearchical, you'll have to install them manually; 
  701. GetNewMBar won't do it for you.  See also 3.5.
  702.  
  703. 3.4) Q: When the user selects my menus, I get strange results back; they 
  704. seem to have different menu IDs than my menus?
  705.  
  706. A: The Menu ID as used by the menu manager is NOT the same thing as the 
  707. MENU resource ID (used in the MBAR resource and with GetMenu()) When you 
  708. create a MENU, ResEdit sets the menu ID to the MENU resource ID, but if 
  709. you re-number the resource, you will have to open the menu in ResEdit 
  710. and change the menu ID using the "Edit MENU ID" menu item.
  711.  
  712. 3.5) Q: I use GetMenu() to find a menu in the menu bar, and then change 
  713. it, but it seems I have a memory leak OR my changes don't "punch 
  714. through"
  715.  
  716. A: GetMenu() is only intended if you don't already have the menu "in 
  717. memory." The call you should use almost all the time is GetMHandle() 
  718. which gets the handle to a menu in the current menu bar by its menu ID 
  719. (not resource id).
  720.  
  721. 3.6) Q: What about pre-emptive multitasking? 
  722.  
  723. A: To the user, the Mac multitasking method, which builds upon each 
  724. application calling WaitNextEvent, GetNextEvent or EventAvail every so 
  725. often and the Process Manager/MultiFinder switching applications only at 
  726. such calls, is at least as good as preemtive multitasking, because the 
  727. present system priotitizes user interface responsiveness over everything 
  728. else.  The only shortfall about this is formatting floppies, which locks 
  729. up the Mac CPU.  This is because the Mac floppy controller is really 
  730. stupid, and would happen even if the Mac multitasked preemptively.
  731.  
  732. There IS "real" pre-emptive multitasking available for use in Mac 
  733. applications; the expensive way is buying A/UX 3.0 which can have Mac 
  734. applications written as UNIX processes; the cheap way is installing the 
  735. Thread Manager which will allow you to create pre-emptive threads.  
  736. However, the restrictions on those threads are the same as those on Time 
  737. Manager tasks: don't call any function in an unloaded segment, and don't 
  738. call QuickDraw or any toolbox call which may move memory (which are most 
  739. ToolBox calls; paradoxally, BlockMove is safe :-) as are, surprisingly, 
  740. FSRead and FSWrite).  The latest word from Apple is that this 
  741. preemptive support is going away, to be replaced by something else in 
  742. Copland.
  743.  
  744. There are several problems with making the Mac OS preemptive; including 
  745. apps that draw outside their windows or directly to screen, user 
  746. dragging and other issues.  The system is being reimplemented for 8.0 
  747. (Copland) to solve these problems.
  748.  
  749. *4* Files
  750.  
  751. 4.1) Q: How do I tell fopen() to open a file the user has selected using 
  752. StandardGetFile?
  753.  
  754. A: The "standard" ANSI C file functions are less than well suited for 
  755. the Macintosh way of doing things.  However, if you are doing a port for 
  756. your own enjoyment and benefit (or maybe for in-house work) you can use 
  757. the following function: (see below about converting a wdRefNum into a 
  758. vRefNum/parID pair)
  759.  
  760. *code*
  761. FILE *
  762. fopen_mac ( short vRefNum , long parID , char * fileName , char * mode ) {
  763.  
  764. short oldVol ;
  765. short aVol ;
  766. long aDir , aProc ;
  767. FILE * ret = NULL ;
  768.  
  769.     if ( GetVol ( NULL , & oldVol ) ) {
  770.         return NULL ;
  771.     }
  772.     if ( GetWDInfo ( oldVol , & aVol , & aDir , & aProc ) ) {
  773.         return NULL  ;
  774.     }
  775.     if ( HSetVol ( NULL , vRefNum , parID ) ) {
  776.         return NULL ;
  777.     }
  778.     ret = fopen ( fileName , mode ) ;
  779.     if ( HSetVol ( NULL, aVol , aDir ) ) {
  780.         /* an error we can't currently handle */
  781.     }
  782.     if ( SetVol ( NULL, oldVol ) ) {
  783.         /* an error we can't currently handle */
  784.     }
  785.     return ret ;
  786. }
  787. *end*
  788.  
  789. All of the above is necessary for one reason or another - if you are 
  790. interested, by all means look HSetVol up in Think Reference 2.0 or New 
  791. Inside Mac: Files.
  792.  
  793. In older versions of MPW; this wouldn't work since the MPW libraries 
  794. used to do a GetVol and explicitly use that value by itself.
  795.  
  796. 4.2) Q: When can I use the HOpen, HCreate etc file calls? Are they only 
  797. System 7 calls?
  798.  
  799. A: All the HXxx calls that take a vRefNum and parID as well as the file 
  800. name are implemented in glue that works on any system that has HFS 
  801. (meaning 3.2 and up with the HD20 INIT, and all systems from System 6 
  802. and up)
  803.  
  804. The glue is available in MPW 3.2 and up, and Think C 5.0 and up.  This 
  805. goes for all HXxx calls except HOpenDF; therefore, if you are interested 
  806. in System 6 compatibility, use HOpen instead and make sure you don't 
  807. allow file names beginning with a period.
  808.  
  809. 4.3) Q: Why do you say wdRefNum sometimes and vRefNum sometimes? 
  810. Why do you say parID sometimes and dirID sometimes? 
  811.  
  812. A: When the Mac first made an appearance in 1984, it identified files by 
  813. using a vRefNum (volume reference number meaning a floppy disk or later 
  814. hard disk) and a name.  Once HFS saw the light of day, folders within 
  815. folders became a reality, and you needed a dirID as well to point out 
  816. what folder you really meant on the volume.  However, older programs 
  817. that weren't being rewritten still knew nothing about directory IDs, so 
  818. Apple had SFGetFile make up "fake" vRefNums that didn't just specify a 
  819. volume, but also a parent folder.  These are called wdRefNums (for 
  820. working directory) and were a necessary evil invented in 1985.  You 
  821. should not create (or, indeed, use) wdRefNums yourself.
  822.  
  823. There is a system-wide table that maps wdRefNums onto vRefNum/parID 
  824. pairs.  There is a limit to the size of this table.  A dirID and a parID 
  825. is almost the same thing; you say "parID" when you mean the folder 
  826. something is in, while you say a "dirID" when you mean the folder 
  827. itself.  If you for instance have a folder called "Foo" with a folder 
  828. called "Bar" in it, the parID for "Bar" would be the dirID for "Foo."
  829.  
  830. 4.4) Q: How do I convert a wdRefNum as returned by SFGetFile 
  831. into a vRefNum/parID pair to use with the HXxx calls?
  832.  
  833. A: Use GetWDInfo, which is declared as: 
  834.  
  835. Pascal OSErr GetWDInfo ( short wdRefNum , short * vRefNum , long * parID 
  836. , OSType * procID ) ;
  837.  
  838. The procID parameter must be non-NULL and point to an OSType variable, 
  839. but the value of that variable can and should be ignored.
  840.  
  841. It is recommended that, as soon as you get your hands on a wdRefNum, for 
  842. instance from SFGetFile, you directly convert it into a vRefNum/parID 
  843. pair and always use the latter to reference the folder.
  844.  
  845. 4.5) Q: How do I select a folder using SFGetFile? 
  846.  
  847. A: This requires a custom dialog with a filter proc.  It is too 
  848. complicated to show here, but not totally impossible to comprehend.  
  849. There is sample code on ftp.apple.com, in the directory dts/snippets, on 
  850. how to do this.
  851.  
  852. 4.6) Q: How do I get the full path of a file referenced by a vRefNum, 
  853. parID and name?
  854.  
  855. A: You don't. 
  856.  
  857. OK, I cheated you.  There is exactly ONE valid reason to get the full 
  858. path of a file (or folder, for that matter) and that is to display its 
  859. location to the user in, say, a settings dialog.  To actually save the 
  860. location of the file you should do this: (assuming the file is in an 
  861. FSSpec called theFile - you can use FSSpecs in your program even if you 
  862. don't run under System 7; just make your own MyFSMakeFSSpec that fills 
  863. in the FSSpec manually if it's not implemented)
  864.  
  865. *code*
  866. if ( ! aliasManagerAvailable ) { /* System 6 ? */
  867.     GetVolumeName ( theFile -> vRefNum , vName ) ;
  868.     GetVolumeModDate ( vRefNum , & date ) ;
  869.     Save ( vName , date , parID , fileName ) ;
  870. } else {
  871.     NewAlias ( NULL , theFile , & theAlias ) ;
  872.     Save ( theAlias ) ;
  873.     DisposeHandle ( ( Handle ) theAlias ) ;
  874. }
  875. *end*
  876.  
  877. If you are really concerned about these issues (of course you are!) you 
  878. should save BOTH of these methods when available, and load back whatever 
  879. is there that you can handle; since users may be using your application 
  880. in a mixed System 6/System 7 environment.
  881.  
  882. To get back to the file is left as an exercise for the reader. 
  883.  
  884. To open a file using fopen() or the Pascal equivalent, see above about 
  885. using and not using HSetVol.
  886.  
  887. 4.7) Q: What about actually getting the full path for a file? I promise 
  888. I will only use it to show the location of a file to the user!
  889.  
  890. A: Enter PBGetCatInfo, the Vegimatic of the Mac file system.  Any Mac 
  891. hacker of knowledge has taken this system call to his heart.  Note that 
  892. this sample code isn't all there, but should point you in the right 
  893. direction:
  894.  
  895. *code*
  896. Boolean IsFolder(FSSpec *fs) // this function is called later
  897. {
  898.         CInfoPBRec rec;
  899.  
  900.         rec.hFileInfo.ioNamePtr = fs -> name;
  901.         rec.hFileInfo.ioVRefNum = fs -> vRefNum;
  902.         rec.hFileInfo.ioDirID = fs -> parID;
  903.  
  904.  
  905.         if ( !fs -> name [ 0 ] )
  906.         {
  907.                 rec . hFileInfo . ioFDirIndex = 0 ;
  908.         } else
  909.         {
  910.                 rec . hFileInfo . ioFDirIndex = -1 ;
  911.         }
  912.  
  913.         rec . hFileInfo . ioFVersNum = 0 ;
  914.         PBGetCatInfoSync (&rec);
  915.  
  916.         return(!rec.hFileInfo.ioFlAttrib & 0x10);
  917. }
  918. *end*
  919.  
  920. *code*
  921. OSErr GetFolderParent(FSSpec *fss, FSSpec *parent)
  922. {
  923.     CInfoPBRec rec;
  924.     short err;
  925.  
  926.     *parent = *fss;
  927.     rec.hFileInfo.ioNamePtr = parent -> name ;
  928.     rec.hFileInfo.ioVRefNum = parent -> vRefNum ;
  929.     rec.hFileInfo.ioDirID = parent -> parID ;
  930.  
  931.     if ( !parent -> name [ 0 ] )  // dougw -- neg of FAQ
  932.     {
  933.         rec . hFileInfo . ioFDirIndex = 0 ;
  934.     }
  935.     else
  936.     {
  937.         rec . hFileInfo . ioFDirIndex = -1 ;
  938.     }
  939.  
  940.     rec . hFileInfo . ioFVersNum = 0 ;
  941.     err = PBGetCatInfoSync ( & rec ) ;
  942.  
  943.     if ( ! ( rec . hFileInfo . ioFlAttrib & 0x10 ) ) { /* Not a folder */
  944.         if ( ! err ) {
  945.             err = dirNFErr ;
  946.         }
  947.     } else {
  948.         parent -> parID = rec . dirInfo . ioDrParID ;
  949.         BlockMove(rec.dirInfo.ioNamePtr, parent->name, rec.dirInfo.ioNamePtr[0]);
  950.     }
  951.     return err ;
  952. }
  953. *end*
  954.  
  955. *code*
  956. OSErr GetFullPathHandle ( FSSpec * fss , Handle * h )
  957. {
  958.     Handle  tempH = NULL;
  959.     FSSpec fs = * fss ;
  960.     FSSpec sSpec;
  961.  
  962.     if(*h == NULL) // allocate a handle if needed
  963.     {
  964.         *h = NewHandle(0);
  965.     }
  966.  
  967.     while ( fs . parID > 1 )
  968.     {
  969.         tempH = NULL ;
  970.         PtrToHand ( & fs . name [ 1 ] , & tempH , fs . name [ 0 ] ) ;
  971.         PtrAndHand ( ( void * ) ":" , tempH , 1 ) ;
  972.         HandAndHand ( * h , tempH ) ;
  973.         SetHandleSize ( * h , 0L ) ;
  974.         HandAndHand ( tempH , * h ) ;
  975.         DisposeHandle ( tempH ) ;
  976.  
  977.         tempH = NULL ;
  978.         GetFolderParent ( & fs , & sSpec ) ;
  979.         fs = sSpec ;
  980.     }
  981.     
  982.     // fs should now contain info about the volume itself
  983.     PtrToHand ( & fs . name [ 1 ] , & tempH , fs . name [ 0 ] ) ;
  984.     PtrAndHand ( ( void * ) ":" , tempH , 1 ) ;
  985.     HandAndHand ( * h , tempH ) ;
  986.     SetHandleSize ( * h , 0L ) ;
  987.     HandAndHand ( tempH , * h ) ;
  988.     DisposeHandle ( tempH ) ;
  989.     tempH = NULL ;
  990.  
  991.     if (!IsFolder ( fss ) )
  992.     {
  993.         SetHandleSize ( * h , GetHandleSize ( * h ) - 1 ) ;
  994.     }
  995.  
  996.     DisposeHandle(tempH);
  997.     return 0 ;
  998. }
  999. *end*
  1000.  
  1001. 4.8) Q: So how do I get the names of the files in a directory? 
  1002.  
  1003. A: You use PBGetCatInfo again, but this time you set ioFDirIndex to 1 or 
  1004. more (you need to know the dirID and vRefNum of the folder you're 
  1005. interested in) You then call PBGetCatInfoSync for values of ioFDirIndex 
  1006. from 1 and up, until you get an fnfErr.  Any other err means you are not 
  1007. allowed to get info about THAT item, but you may be for the next.  Then 
  1008. collect the names in the string you made ioNamePtr point to as you go 
  1009. along.  Note that you need to fill in the ioDirID field for each 
  1010. iteration through the loop, and preferably clear the ioFVersNum as well.
  1011.  
  1012. Note that the contents of a directory may very well change while you are 
  1013. iterating over it; this is most likely on a file server that more than 
  1014. one user uses, or under System 7 where you run Personal File Share.
  1015.  
  1016. 4.9) Q: How do I find the name of a folder for which I only know the 
  1017. dirID and vRefNum?
  1018.  
  1019. A: You call (surprise!) PBGetCatInfo! Make ioNamePtr point to an empty 
  1020. string (but NOT NULL) of length 63 (like, an Str63) and ioFDirIndex 
  1021. negative (-1 is a given winner) - this makes PBGetCatInfo return 
  1022. information about the vRefNum/dirID folder instead of the file/folder 
  1023. specified by vRefNum, parID and name.
  1024.  
  1025. 4.10) Q: How do I make the Finder see a new file that I created? Or if I 
  1026. changed the type of it; how do I display a new icon for it?
  1027.  
  1028. A: You call (surprise!) PBGetCatInfo followed by PBSetCatInfo for the 
  1029. FOLDER the file is in.  Inbetween, you should set ioDrMdDat to the 
  1030. current date&time.  Code:
  1031.  
  1032. *code*
  1033. OSErr
  1034. TouchFolder ( short vRefNum , long parID ) {
  1035.  
  1036. CInfoPBRec rec ;
  1037. Str63 name ;
  1038. short err ;
  1039.  
  1040.     rec . hFileInfo . ioNamePtr = name ;
  1041.     name [ 0 ] = 0 ;
  1042.     rec . hFileInfo . ioVRefNum = vRefNum ;
  1043.     rec . hFileInfo . ioDirID = parID ;
  1044.     rec . hFileInfo . ioFDirIndex = -1 ;
  1045.     rec . hFileInfo . ioFVersNum = 0 ;
  1046.     err = PBGetCatInfoSync ( & rec ) ;
  1047.     if ( err ) {
  1048.         return err ;
  1049.     }
  1050.     GetDateTime ( & rec . dirInfo . ioDrMdDat ) ;
  1051.     rec . hFileInfo . ioVRefNum = vRefNum ;
  1052.     rec . hFileInfo . ioDirID = parID ;
  1053.     rec . hFileInfo . ioFDirIndex = -1 ;
  1054.     rec . hFileInfo . ioFVersNum = 0 ;
  1055.     rec . hFileInfo . ioNamePtr [ 0 ] = 0 ;
  1056.     err = PBSetCatInfoSync ( & rec ) ;
  1057.     return err ;
  1058. }
  1059. *end*
  1060.  
  1061. 4.11) Q: Aren't we done with PBGetCatInfo soon? 
  1062.  
  1063. A: Well, it turns out that you can also find out whether an FSSpec is a 
  1064. file or a folder by calling PBGetCatInfo and check bit 4 (0x10) of 
  1065. ioFlAttr to see whether it is a folder.  You may prefer to call 
  1066. ResolveAliasFile for this instead.
  1067. You can also check the script of the file's title using PBGetCatInfo and 
  1068. check the ioFlFndrXInfo field if you want to work with other script 
  1069. systems than the Roman system.
  1070.  
  1071. Another common use is to find out how many items are in a folder; the 
  1072. modification date of something or the correct capitalization of its name 
  1073. (since the Mac file system is case independent BUT preserves the case 
  1074. the user uses)
  1075.  
  1076. 4.12) Q: How do I set what folder should initially be shown in the 
  1077. SFGetFile boxes?
  1078.  
  1079. A: You stuff the dirID you want to show into the lo-mem global 
  1080. CurDirStore, and the NEGATIVE of the vRefNum you want into the lo-mem 
  1081. global SFSaveDisk.
  1082.  
  1083. If you are using CustomGetFile and return sfSelectionChanged from an 
  1084. "init" message handler, you must remember to clear the script code, else 
  1085. the selection will not change.
  1086.  
  1087. 4.13) Q: How do I find the folder my application started from? How do I 
  1088. find the application file that's running?
  1089.  
  1090. A: Under System 7, you call GetProcessInformation using the 
  1091. ProcessSerialNumber kCurrentProcess with a pointer to an existing FSSpec 
  1092. in the parameter block.  This will give you your file, and, by using the 
  1093. vRefNum and parID, the folder the application is in.
  1094.  
  1095. *code*
  1096. OSErr   CurrentProcessLocation(FSSpec *applicationSpec)
  1097. {
  1098.     ProcessSerialNumber currentPSN;
  1099.     ProcessInfoRec info;
  1100.     
  1101.     currentPSN.highLongOfPSN = 0;
  1102.     currentPSN.lowLongOfPSN = kCurrentProcess;
  1103.     info.processInfoLength = sizeof(ProcessInfoRec);
  1104.     info.processName = NULL;
  1105.     info.processAppSpec = applicationSpec;
  1106.     return ( GetProcessInformation(¤tPSN, &info) );
  1107. }
  1108. *end*
  1109.  
  1110. Beware from writing to your applications resource or data forks; the 
  1111. former breaks on CDs/write protected floppies/file servers/virus 
  1112. checkers, the latter fails on PowerPC as well as in the above cases.
  1113.  
  1114. 4.14) Q: When can I use those nifty, easy to use FSSpec calls?
  1115.  
  1116. A: In Systems >= 7, in System 6 with QuickTime installed, in any system 
  1117. if you use the FSpCompat functions provided by MoreFiles [see below].
  1118.  
  1119. 4.15) Q: I hate dealing with the low-level file manager stuff;  why 
  1120. didn't Apple provide a complete high-level interface using FSSpecs?
  1121.  
  1122. A: Good question.  Apple, in the guise of Jim Luther of Mac Developer 
  1123. Technical Support, has written a library called MoreFiles, which not 
  1124. only provides a high-level interface to low-level file stuff, but 
  1125. provides FSSpec glue for Systems below 7.  MoreFiles is available on the 
  1126. Developer CD's (see above) and also at Appple's developer ftp site.
  1127.  
  1128. *5* Imaging with QuickDraw
  1129.  
  1130. 5.1) Q: Why is CopyBits so slow? 
  1131.  
  1132. A: It is not.  It just requires some hand-holding to get good results.  
  1133. The main rules are: Make sure the source and destination pixMaps are of 
  1134. the same depth.
  1135.  
  1136. Make sure the front color is black and the back color is white.
  1137.  
  1138. Use srcCopy and don't use a masking region, unless it's rectangular. 
  1139.  
  1140. Copy to an unclipped window (the frontmost window).  Make sure the 
  1141. ctSeed values of the source pixMap and dest pixMap match. 
  1142.  
  1143. Copying few and large pixMaps is faster than copying many and small 
  1144. ones.  Icon-sized sprites count as small ones.
  1145.  
  1146. Make sure your source bitmap or pixelMap has the same alignment, when 
  1147. adjusted for the source and destination rect expressed in global screen 
  1148. coordinates.  The necessary alignment is 32 bits (4 bytes), although 128 
  1149. bit (16 byte) alignment is probably even better on 68040 macs and won't 
  1150. hurt on other macs.
  1151.  
  1152. Example of global alignment: 
  1153.  
  1154. Your window is positioned at (42,100) (H,V) 
  1155.  
  1156. Your destination rectangle is (10,20)-(74,52) 
  1157.  
  1158. The alignment coefficient of the rectangle in global coordinates is 
  1159. (42+10)*bitDepth where bitDepth is one of 1,2,4,8,16 or 32.
  1160.  
  1161. Make sure your source pixmap rect has the same coeffecient modulo your 
  1162. alignment factor (in bits) For black&white macs, this is still true, 
  1163. although bitDepth is fix at 1.  Offscreen pixMaps can calculate with a 
  1164. "global posistion" of 0,0 and get correct results.
  1165.  
  1166. 5.2) Q: Why is CopyBits still too slow? 
  1167.  
  1168. A: Because there is always some overhead involved in calling QuickDraw; 
  1169. you have the trap dispatcher, clipping checks, and checking whether the 
  1170. CopyBits call is being recorded in a PICT handle (if you called 
  1171. OpenPicture)
  1172.  
  1173. If you can't live with this, look at 4.8 below, but PLEASE try and make 
  1174. CopyBits work, and retain the CopyBits code in your application, so 
  1175. users with special monitors (accellerator cards, PowerBook color 
  1176. screens, Radius Pivot screens) can still play your game.  (non-game 
  1177. applications don't need more speed than CopyBits can give at its max.  
  1178. Promise!)
  1179.  
  1180. 5.3) Q: What is the fastest way to set one pixel? 
  1181.  
  1182. A: On 68k Macs, NOT SetCPixel()! Assuming you have the correct ForeColor() 
  1183. set, you can set the pen size to (1,0) and call Line (0,1)
  1184.  
  1185. I have heard PaintRect is good for this but requires slightly more code.  
  1186. Using PaintRect eliminates a trap call.
  1187.  
  1188. 5.4) Q: Why do pictures I record suddenly draw as empty space or not 
  1189. draw at all?
  1190.  
  1191. A: When recording pictures, you have to set the clipping area to exactly 
  1192. the frame of the picture you are recording.  This is because it is 
  1193. initally set at -32768,32727 in both directions, and offsetting the 
  1194. picture even one pixel when drawing it will result in the region 
  1195. wrapping around and becoming empty.
  1196.  
  1197. When recording pictures, do this: 
  1198.  
  1199. *code*
  1200. PicHandle h = OpenPicture ( & theRect ) ;
  1201. ClipRect ( & theRect ) ;
  1202.     /* draw the picture */
  1203. ClosePicture ( ) ;
  1204. *end*
  1205.  
  1206. 5.5) Q: Where can I find the format of picture files and 
  1207. resources? 
  1208.  
  1209. A: The format of a picture resource version 1 is defined in a technical 
  1210. note.  This format is obsolete.
  1211.  
  1212. The format of a picture resource version 2 is defined in Old Inside Mac 
  1213. vol V, with addenda in Old Inside Mac vol VI.
  1214.  
  1215. Some things happen with QuickTime compressed pictures; try the Inside 
  1216. Mac: QuickTime book or turn to Inside Mac: Imaging with QuickDraw which 
  1217. is the definite reference on QuickDraw.
  1218.  
  1219. The format of a picture file is the same as that of a picture resource 
  1220. with 512 added 0 bytes in front.
  1221.  
  1222. 5.6) Q: GWorlds? 
  1223.  
  1224. A: What about them?  They're great.  Look them up in IM: Imaging With 
  1225. QuickDraw.  Don't forget to SetGWorld back to what it was before calling 
  1226. WaitNextEvent.
  1227.  
  1228. 5.7) Q: How do I find the current depth of the screen? 
  1229.  
  1230. A: My question to you is: What screen? Many macs have more than one 
  1231. screen attached.  You can use GetDeviceList and walk the devices to find 
  1232. the screen you're looking for (use TestDeviceAttribute to see whether 
  1233. it's a screen) or you can call GetMaxDevice() to find the deepest device 
  1234. your window intersects.
  1235.  
  1236. Once you have the device handle, finding the depth is just a 
  1237. matter of looking at the gdPMap pixMapHandle, and dereference it 
  1238. to the pmSize field. Done. 
  1239.  
  1240. 5.8) Q: Why is it a bad idea to draw directly to screen? 
  1241.  
  1242. A: Because of several reasons: 
  1243.  
  1244. - You will be incompatible with future display hardware. 
  1245.  
  1246. - You will be incompatible with some present-day display 
  1247. hardware, such as Radius Pivots and PowerBook color screens. 
  1248.  
  1249. - You have to think about a lot of things; testing it all on 
  1250. your own machine is not possible and the chances of crashing are 
  1251. great. 
  1252.  
  1253. - You will be incompatible with future hardware where devices 
  1254. may live in some unaccessible I/O space. 
  1255.  
  1256. 5.9) Q: But I really need to do it.  I can't make my animation into a 
  1257. QuickTime movie, and CopyBits is too slow, even when syncing to the 
  1258. screen retrace and with my source GWorld aligned properly.
  1259.  
  1260. A: You have to prepare yourself, and ask these questions: 
  1261.  
  1262. - Do I want to support all screens, or just 8-bit devices?
  1263.  
  1264. - Do I have a few weeks of free time to make it work? 
  1265.  
  1266. - Do I want to get nasty mail when I break on some hardware and 
  1267.    have to rev the application - even if I may not be able to get 
  1268.    ahold of the hardware that makes it break? 
  1269.  
  1270. If all you're doing is rendering an image pixel-by-pixel or 
  1271. line-by-line, maybe you can draw directly into an offscreen 
  1272. pixMap/GWorld and then CopyBits the entire GWorld to screen? 
  1273. That will be more compatible, especially if you use the 
  1274. keepLocal flag when creating the GWorld. 
  1275.  
  1276. 5.10) Q: Okay, so how do I get the base address of the screen? 
  1277.  
  1278. A: "The" screen? Which screen? There may be several. The base 
  1279. address may be on an accellerated screen card. There may be more 
  1280. than one screen covering the same desktop area. 
  1281.  
  1282. Due to unfortunate circumstances, there is a bug in 
  1283. GetPixBaseAddr() that causes it to return incorrect results for 
  1284. early versions of System 7. Instead, get the baseAddr directly 
  1285. from the gdPMap handle of the GDHandle for the screen you draw 
  1286. to. This address may need switching to 32bit mode to be valid. 
  1287.  
  1288. 5.11) Q: Quit stalling and give me code! 
  1289.  
  1290. A: Okay, but I'll let you sweat over Inside Mac to figure out 
  1291. what it does. All of it is important; believe me! To make this 
  1292. code run faster, a lot of the things it does can be done once 
  1293. before starting to draw. 
  1294.  
  1295. Make sure that you have a window that covers the area where you 
  1296. are drawing, so other windows will not be overdrawn. Also make 
  1297. sure that you do not do direct-to-screen-drawing while you are 
  1298. in the background. 
  1299.  
  1300. *code*
  1301. /* This is presently untested code */
  1302. /* Value is dependent on what depth the screen has */
  1303. /* This code doesn't work on non-color-quickdraw Macs (i e the MacClassic) */
  1304. /* "where" is in GLOBAL coordinates */
  1305. void
  1306. SetPixel ( Point where , unsigned long value ) {
  1307.  
  1308. Rect r ;
  1309. GDHandle theGD ;
  1310. char * ptr ;
  1311. long rowBytes ;
  1312. short bitsPerPixel ;
  1313. PixMapHandle pmh ;
  1314. Boolean oldMode ;
  1315.  
  1316.     r . left = where . h ;
  1317.     r . top = where . v ;
  1318.     r . right = r . left + 1 ;
  1319.     r . bottom = r . top + 1 ;
  1320.     theGD = GetMaxDevice ( & r ) ;
  1321.     if ( theGD ) {
  1322.         where . v -= ( * theGD ) -> gdRect . left ;
  1323.         where . h -= ( * theGD ) -> gdRect . top ;
  1324.         pmh = ( * theGD ) -> gdPMap ;
  1325.         rowBytes = ( ( * pmh ) -> rowBytes ) & 0x3fff ;
  1326.         ptr = ( char * ) ( * pmh ) -> baseAddr ;
  1327.         bitsPerPixel = ( * pmh ) -> pixelSize ;
  1328.         oldMode = true32b ;
  1329.         ptr += where . v * rowBytes ;
  1330.         SwapMMUMode ( & oldMode ) ;
  1331.         switch ( bitsPerPixel ) {
  1332.         case 1 :
  1333.             if ( value & 1 ) { 
  1334.                 ptr [ where . h >> 3 ] |= ( 128 >> ( where . h & 7 ) ) ;
  1335.             } else {
  1336.                 ptr [ where . h >> 3 ] &= ~( 128 >> ( where . h & 7 ) ) ;
  1337.             }
  1338.             break ;
  1339.         case 2 :
  1340.             ptr [ where . h >> 2 ] &= ( 192 >> 2 * ( where . h & 3 ) ) ;
  1341.             ptr [ where . h >> 2 ] |= ( value & 3 ) << 2 * ( 3 - ( where . h & 3 ) ) ;
  1342.             break ;
  1343.         case 4 :
  1344.             ptr [ where . h >> 1 ] &= ( where . h & 1 ) ? 0xf : 0xf0 ;
  1345.             ptr [ where . h >> 1 ] |= ( value & 15 ) << 4 * ( 1 - ( where . h & 1 ) ) ;
  1346.             break ;
  1347.         case 8 :
  1348.             ptr [ where . h ] = value ;
  1349.             break ;
  1350.         case 16 :
  1351.             ( ( unsigned short * ) ptr ) [ where . h ] = value ;
  1352.             break ;
  1353.         case 32 :
  1354.             ( ( unsigned long * ) ptr ) [ where . h ] = value ;
  1355.             break ;
  1356.         default :
  1357.             abort ( ) ; /* Should never get here */
  1358.         }
  1359.         SwapMMUMode ( & oldMode ) ;
  1360.     }
  1361. }
  1362. *end*
  1363.  
  1364. *6* Text
  1365.  
  1366. 6.1) Q: How do I get TextEdit to display more than 32k of text?
  1367.  
  1368. A: You don't.  Truly, it's not worth it.  There's a call-for-call 
  1369. TextEdit replacement called TE32k which does > 32k text, and is 
  1370. available from any recent Info-Mac mirror.  It doesn't do styled text, 
  1371. though.
  1372.  
  1373. 6.2) Q: How do I get TextEdit to display more than 32k of __styled__ 
  1374. text *and* embedded objects in the text (such as pictures)?
  1375.  
  1376. WASTE, available at ftp://ghost.dsi.unimi.it/pub2/papers/piovanel, is a 
  1377. vast improvement over TextEdit.  Version 1.0 does >32k styled text 
  1378. retains compatibility with the TextEdit style scrap (which is used to 
  1379. store styled text in files such as SimpleText's, as well as in the 
  1380. clipboard), includes source code and is freeware.  Really worth the 
  1381. download.  Version 1.1 adds embedded objects within the text, such as 
  1382. pictures, intelligent cut-and-paste, built-in Drag Manager support, 
  1383. built-in Undo support.  1.1 is currently in alpha, but seems to be very 
  1384. stable.
  1385.  
  1386. "But," you nervously stutter, "WASTE is in Pascal!  And it's munged so 
  1387. that it won't work as an imported library w/Metrowerks C!  What now?"
  1388.  
  1389. Dan Crevier is maintaining a C port of WASTE, and the current version 
  1390. along with other WASTE goodies is at <ftp://rhino.harvard.edu/pub/dan/>.
  1391.  
  1392. 6.3) Q: I'm too back-asswards to use WASTE 1.1.  How do I include 
  1393. pictures in text using TextEdit?
  1394.  
  1395. A: There's no really easy way (such as a TEAddPict() call), and it will 
  1396. be a nasty kludge if you do get it working, but if you can live with 
  1397. that, here's how to do it.  I do recommend that you take a look at Q 
  1398. 6.2, above.
  1399.  
  1400. Write an algorithm to get the position of a special marker character 
  1401. [Teach/SimpleText uses option-space] or text attribute that the user 
  1402. will insert wherever he wants a picture.  Pass this position to a 
  1403. function similar to the one below.
  1404.  
  1405. *code* 
  1406. /*
  1407.     TEDrawPicture
  1408.     Draw a picture within TextEdit's text.
  1409.     
  1410.     input:
  1411.         pos - the position of the special character in the text where the user 
  1412.                 wants a picture.
  1413.         r   - size of picture
  1414.     
  1415.     output:
  1416.         r   - frame in which picture was drawn
  1417. */
  1418.  
  1419. void TEDrawPicture(short pos,PicHandle pic,Rect &r,TEHandle theTE)
  1420. {
  1421.     Point   bottomLeft;  //I think TT/ST uses topleft
  1422.     
  1423.     bottomLeft = TEGetPoint(pos, theTE);
  1424.     
  1425.     r.right = bottomLeft.h + (r.right - r.left);
  1426.     r.top = bottomLeft.v - (r.bottom - r.top);
  1427.     r.left = bottomLeft.h;
  1428.     r.bottom = bottomLeft.v;
  1429.     
  1430.     DrawPicture(pic, &r);
  1431. }
  1432.  
  1433. *end*
  1434.  
  1435. I'll leave selection and hiliting as an exercise for the reader (don't 
  1436. ya love it when people say that?).
  1437.  
  1438. Thereotically, it should be possible to kludge up TextEdit to the point 
  1439. where it would treat pictures as if they were actually letters (rather big 
  1440. letters, but letters just the same).  That's what the width and word break 
  1441. hooks are for, after all.  However, this would be a lot of Work, and I've 
  1442. never seen it done.  One is lead to believe that it's less work to create 
  1443. an improved version of TextEdit from the ground up with picture support.  
  1444. WASTE 1.1, in fact, does this rather nicely.
  1445.  
  1446. 6.4) Q: I have all this money, and I want to get rid of it. How do I
  1447. edit more than 32k of styled text now?
  1448.  
  1449. A: There are at least three solutions.
  1450.  
  1451. 1) The Galaxy application framework comes with a styled text editting
  1452. engine which does more than 32k of text. It also happens to support
  1453. cross-platform application development. Pricing starts at $10000.
  1454. <galaxy@visix.com>
  1455.  
  1456. 2) DataPak is selling a cross-platform library called "PAIGE".  It is 
  1457. written to be customizable to any extent, and you can do _anything_ in 
  1458. it (want quicktime movies that play and flow with the text while 
  1459. editting? Three pages of code; you can adapt their picture sample code.) 
  1460. Available for Mac, Windows & Never Trusted and Power Mac.  Pricing at 
  1461. $5000 ($25000 for source code) - it might be cheaper if you talk to 
  1462. them.  Customer support is reputed to be "lousy".
  1463.  
  1464. 3) Or you could use WASTE 1.1 with it's embedded objects implementation 
  1465. (want quicktime movies that play and flow with the text while editing? 
  1466. One page of code, if that much.)
  1467.  
  1468. 6.5) Q: How do I convert from a string to a floating point type?
  1469.  
  1470. A: Once you've got an Str255, you want to call the routine 
  1471. StringToExtended to change the number into type extended80, which is the 
  1472. 80-bit floating point type.  The nice thing about StringToExtended is 
  1473. that it even works in funky foreign language scripts like Chinese.  To 
  1474. use the routine, you must pass it not only the Str255 that you want 
  1475. converted, but also the results of the StringToFormatRec routine and the 
  1476. GetIntlResourceTable routine.  The documentation is generally difficult, 
  1477. so I'll describe the parameters and give you a code example below.  
  1478. Here's what you pass to StringToExtended:
  1479.  
  1480. - source:
  1481. Obviously the string representation of the number.
  1482.  
  1483. - myFormatRec:
  1484. This is simply the format that you expect the number to be.  For 
  1485. example, if you wanted a positive integer with up to 3 decimal places, 
  1486. you would want the format to be "###".  (The "#" symbol means a non-zero 
  1487. filled digit, whereas a "0" would mean zero filled.) If you wanted an 
  1488. floating point exponential notation with up to 2 digit integer portion, 
  1489. exactly 2 digit decimal portion, and exactly 1 digit after the "E", your 
  1490. format would be "##.00E+0".  (Actually, in Canada, you folks might use a 
  1491. "," instead of a "." for the decimal point; if you do, then you would 
  1492. put the locally correct symbol in there.) In a format string, you can 
  1493. put the format for a positive value, a negative value, and 0 seperated 
  1494. by semicolons (e.g.  "##.00E+0;-##.00E+0;0.00E+0").
  1495.  
  1496. But myFormatRec is not the format string itself, but is an internal 
  1497. format that you get from calling StringToFormatRec.  This is so you can 
  1498. store the format returned to you by StringToFormatRec and use it on 
  1499. different international systems.  There is a nice editor for ResEdit for 
  1500. 'FMAT' resources that lets you type the format string and will call 
  1501. StringToFormatRec for you and create an 'FMAT' resource out of the 
  1502. result.  Then you can load the 'FMAT' at run time and pass it to 
  1503. myFormatRec.
  1504.  
  1505. - partsTable:
  1506. The number parts table from the 'itl4' resource.  If you are using 
  1507. System 7 or later, you call GetIntlResourceTable, asking it for the 
  1508. number parts table.  You don't need to worry about HLock'ing itlHandle 
  1509. because StringToExtended doesn't move memory; just don't do anything 
  1510. between your call to GetIntlResourceTable and the StringToFormatRec 
  1511. routine.  If you are using System 6, you need to perform the 
  1512. GetIntlResourceTable by hand.  It's a few lines of code; left as an 
  1513. exercise to the reader.
  1514.  
  1515. - x:
  1516. The extended number to put the thing into.
  1517.  
  1518. So, let's say you expect the user to enter a string containing up to 5 
  1519. digits in the integer with a thousand marker between the 3rd and fourth 
  1520. digit, exactly two digits after the decimal, put it in parenthesis if 
  1521. it's negative, and have it just be "0.00" if it's 0.  (I will use "." 
  1522. for the decimal and "," for the thousand marker.  Here's the C code 
  1523. (passing in the source string):
  1524.  
  1525. *code*
  1526. Handle itlHandle;               /* The 'itl4' resource handle */
  1527. long offset, length;            /* Offset-length of parts table */
  1528. NumFormatStringRec myFormatRec; /* Canonical format record */
  1529. extended80 x;                   /* The number to put it into */
  1530.  
  1531. GetIntlResourceTable (smCurrentScript, smNumberPartsTable,
  1532.                       &itlHandle, &offset, &length);
  1533. StringToFormatRec ("\p##,###.00;(##,###.00);0.00",
  1534.                    (NumberParts *)(*itlHandle + offset),
  1535.                    &myFormatRec);
  1536. StringToExtended (source, &myFormatRec,
  1537.                   (NumberParts *)(*itlHandle + offset),
  1538.                   &x);
  1539. *end*
  1540.  
  1541. If you saved a format record in a resource using the 'FMAT' editor 
  1542. (which is really the preferred way to do it), you would change the code 
  1543. to look like this:
  1544.  
  1545. *code*
  1546. Handle itlHandle;                 /* The 'itl4' resource handle */
  1547. long offset, length;              /* Offset-length of parts table */
  1548. NumFormatStringRec **myFormatRec; /* Canonical format resource */
  1549. extended80 x;                     /* The number to put it into */
  1550.  
  1551. myFormatRec = (NumFormatStringRec **)GetResource('FMAT', MY_FMAT);
  1552. GetIntlResourceTable (smCurrentScript, smNumberPartsTable,
  1553.                       &itlHandle, &offset, &length);
  1554. StringToExtended (source, *myFormatRec,
  1555.                   (NumberParts *)(*itlHandle + offset),
  1556.                   &x);
  1557. *end*
  1558.  
  1559. The StringToExtended routines will return a result that will tell you if 
  1560. there are any parsing errors.  Error checking is also left as an 
  1561. exercise to the reader.
  1562.  
  1563. Of course, the reverse of the process (using ExtendedToString) works 
  1564. very much the same way, passing the same sorts of parameters.
  1565.  
  1566. *7* Communications and Networking
  1567.  
  1568. 7.1) Q: How do I get at the serial ports? 
  1569.  
  1570. A: You call OpenDriver for the names "\p.AOut" and "\p.AIn" to get at 
  1571. the modem port, and "\p.BOut" and "\p.BIn" for the printer port.  The 
  1572. function RAMSDOpen was designed for the original Mac with 128 kB of 
  1573. memory and 64 kB of ROM, and has been extinct for several years.
  1574.  
  1575. However, many users use their serial ports for MIDI, LocalTalk, graphic 
  1576. tablets, or what have you and have installed an additional serial port 
  1577. card to get more ports.  What you SHOULD do as a good application is to 
  1578. use the Comm Toolbox Resource Manager to search for serial resources; 
  1579. this requires that the Comms Toolbox is present (true on earlier System 
  1580. 6 with an INIT, on later System 6 and System 7 always, as well as on 
  1581. A/UX) and that you have initialized the comms resource manager.  The 
  1582. exact code follows (adapted from Inside Mac Comms Toolbox):
  1583.  
  1584. *code*
  1585. #include "CommResources.h"
  1586. OSErr
  1587. FindPorts ( Handle * portOutNames , Handle * portInNames , Handle * names , Handle * iconHandles ) {
  1588.  
  1589. OSErr ret = noErr ;
  1590. short old = 0 ;
  1591. CRMRec theCRMRec , * found ;
  1592. CRMSerialRecord * serial ;
  1593.  
  1594.     * portOutNames = NewHandle ( 0L ) ;
  1595.     * portInNames = NewHandle ( 0L ) ;
  1596.     * names = NewHandle ( 0L ) ;
  1597.     * iconHandles = NewHandle ( 0L ) ;
  1598.     while ( ! ret ) {
  1599.         theCRMRec . crmDeviceType = crmSerialDevice ;
  1600.         theCRMRec . crmDeviceID = old ;
  1601.         found = ( CRMRec * ) CRMSearch ( ( QElementPtr ) & theCRMRec ) ;
  1602.         if ( found ) {
  1603.             serial = ( CRMSerialRecord * ) found -> crmAttributes ;
  1604.             old = found -> crmDeviceID ;
  1605.             PtrAndHand ( & serial -> outputDriverName , * portOutNames ,
  1606.                 sizeof ( serial -> outputDriverName ) ) ;
  1607.             PtrAndHand ( & serial -> inputDriverName , * portInNames ,
  1608.                 sizeof ( serial -> inputDriverName ) ) ;
  1609.             PtrAndHand ( & serial -> name , * names , 
  1610.                 sizeof ( serial -> name ) ) ;
  1611.             PtrAndHand ( & serial -> deviceIcon , * iconHandles ,
  1612.                 sizeof ( serial -> deviceIcon ) ) ;
  1613.         } else {
  1614.             break ;
  1615.         }
  1616.     }
  1617.     return err ;
  1618. }
  1619. *end*
  1620.  
  1621. This will create four handles with the driver names, device names and 
  1622. driver icon handles for all of the available serial devices.  Then let 
  1623. the user choose with a pop-up menu or scrolling list, and save the 
  1624. choice in your settings file.
  1625.  
  1626. You can use OpenDriver, SetReset, SetHShake, SetSetBuf, SerGetBuf and 
  1627. the other Serial Manager functions on these drivers.  To write to the 
  1628. serial port, use FSWrite for synchronous writes that wait until all is 
  1629. written, or PBWrite asynchronously for queuing up data that is supposed 
  1630. to go out but you don't want to wait for it.  At least once each time 
  1631. through your event loop, you should call SerGetBuf on the in driver 
  1632. reference number you got from OpenDriver, and call FSRead for that many 
  1633. bytes - neither more nor less.
  1634.  
  1635. If you are REALLY interested in doing the right thing, you will use the 
  1636. Communications Toolbox Connection Manager instead; this will give you 
  1637. access to modems, direct lines, and networks of various kinds using the 
  1638. same API! Great for stuff like BBSes that may be on a network as well 
  1639. etc.  The Comms Toolbox also provides modularized terminal emulation 
  1640. and file transfer tools, although the Apple-suplied VT102 tool is pretty 
  1641. lame, as is the VT102 mode of the VT320 tool.  And it seems as though 
  1642. it was designed by people who'd never used a Mac before... more in the 
  1643. Unix style, right down to the lack of documentation and "magicCookie."
  1644.  
  1645. 7.2) Q: Where is a Berkley sockets library for the Mac? 
  1646.  
  1647. A: There are some problems with that.  MacTCP, the Mac Toolbox 
  1648. implementation of TCP/IP, doesn't have an API that looks at all like 
  1649. Berkley sockets.  For instance, there is ONE paramater-block call to do 
  1650. a combined listen()/accept()/bind() - sort of.  I have heard that there 
  1651. may be a socket library available by ftp from MIT but haven't seen it 
  1652. myself.
  1653.  
  1654. There is also a pretty good C++ TCP implementation called GUSI which is 
  1655. easily handled, and it also is callable from C using the Berkley socket 
  1656. API.  Apart from TCP, it also handles "standard" Mac network protocols 
  1657. such as ADSP.  The big disadvantage is that it is currently only 
  1658. implemented for MPW.  The ftp site is nic.switch.ch, 
  1659. software/mac/src/mpw_c.
  1660.  
  1661. I can also recommend the Communications Toolbox; for the price of using 
  1662. an API that is a bigger pain in the ass than configuring Windoze to use 
  1663. a new peripheral device, you get the benefit of being able to use any 
  1664. kind of connection (TCP tools are available).
  1665.  
  1666. Instead of the Comm Toolbox, one might use Apple's much improved Open 
  1667. Transport architecture.  Preliminary docs are available for ftp at 
  1668. seeding.apple.com.  Apple's new networking products team seems to have 
  1669. it's head screwed on tight.  A refreshing change.
  1670.  
  1671. Novell and Wollogong offer commercial socket-like libraries. 
  1672.  
  1673. 7.3) Q: Where do I find MacTCP? 
  1674.  
  1675. A: You can buy the MacTCP developers kit from APDA.  It is also 
  1676. available on E T O, and if you want saner headers than those, try ftp to 
  1677. seeding.apple.com.  MacTCP (the control panel) is included with System 
  1678. 7.5 and above.
  1679.  
  1680. 7.4) Q: I'm trying to write to the serial port.  It works fine on the 
  1681. following Machines, Quadra700, IIFX, Powerbook 170, Quadra 840av, but 
  1682. freezes on the Duo 230 and 280c.
  1683.  
  1684. A: You need to call SerHShake.  Otherwise you get screwed on some 
  1685. machines without a hardware handshaking cable because the port default to 
  1686. hardware handshaking.
  1687.  
  1688. *8* IAC
  1689.  
  1690. 8.1) Q: What are AppleEvents? 
  1691.  
  1692. A: AppleEvents are a level-5 network protocol.  If you are not familiar 
  1693. with the ISO network stack, this means it's a way of structuring sessions 
  1694. between network entities (programs) that is not dependent on the 
  1695. underlying protocol (such as PPC or TCP/IP) Despite being a network 
  1696. protocol, they can be very useful on Macs that are not on a network.  In 
  1697. short, they provide applications with a comprehensive way to send 
  1698. arbitrary structured data to other applications (or themselves) which 
  1699. receive the events through their main event loop.
  1700.  
  1701. The AppleEvent Object Model is a way of looking at applications and the 
  1702. data they contain, and also a level-6 network protocol.  You _can_ send 
  1703. AppleEvent Object Model data through AppleEvents (and the standard 
  1704. AppleEvents defined in the AppleEvent Registry use it) but you don't have 
  1705. to - unless you want to talk with other applications, of course, then the 
  1706. AEOM is a lingua franca.
  1707.  
  1708. 8.2) Q: What are the four required AppleEvents? 
  1709.  
  1710. A: There are four events your application really must implement if you 
  1711. want to sell it: the kCoreEventClass class, kAEOpenApplication, 
  1712. kAEQuitApplication, kAEOpenDocuments and kAEPrintDocuments events IDs.  
  1713. When you support these events (or any AppleEvents) you will not get 
  1714. startup info through GetAppParams() anymore, unless you run under System 
  1715. 6 of course.  The kAEOpenApplication event will be sent to you when the 
  1716. user double-clicks your app and it's not started yet.  When receiving it, 
  1717. you can put up a new untitled window.
  1718.  
  1719. kAEOpenDocuments is sent when the user double-clicks your apps documents.  
  1720. Note that if the first AppleEvent you receive is a kAEOpenDocuments 
  1721. event, the user started your app by double-clicking its documents.
  1722.  
  1723. kAEPrintDocuments is sent when the user selects your documents and 
  1724. chooses "Print" in the Finder menu.  If this is the first AppleEvent you 
  1725. receive, you should print the documents and then quit the application 
  1726. again; if you received a kAEOpenApplication or kAEOpenDocuments event 
  1727. before this, you should just print the documents and close them when 
  1728. you're done.
  1729.  
  1730. kAEQuitApplication is sent to you when the user chooses "Shutdown" or 
  1731. "Restart" from the Apple Menu.  You should ask the user whether he wants 
  1732. to save any unsaved changed documents, and then quit unless the user 
  1733. presses Cancel.
  1734.  
  1735. Interestingly enough, you can use these four AppleEvents to send even to 
  1736. non-AE-aware applications, and the system will translate these events 
  1737. into fake menu selections for you.
  1738.  
  1739. A good way of shutting down the Finder is to send it a Quit AppleEvent.  
  1740. You should send a Quit AppleEvent to File Sharing Extension before you 
  1741. shut down the Finder, though; the FSE is found by looking for a process 
  1742. with the creator 'hhgg'.
  1743.  
  1744. 8.3) Q: Are there any limits or tradeoffs with AppleEvents? 
  1745.  
  1746. A: As always, more power means more responsibility. 
  1747.  
  1748. AppleEvents sent to applications on other Macs require authentification 
  1749. the first time they are sent.  If the remote Mac allows Guests to link to 
  1750. programs, the INIT AutoGuest 2.0 might help (or the code solution that 
  1751. comes with it and you can build into your application)
  1752.  
  1753. In the first version of the AppleEvent manager, there was a total 64K 
  1754. limit on the size of data and overhead.  This limit has been lifted with 
  1755. the version of the AppleEvent manager that comes with AppleScript.
  1756.  
  1757. AppleEvents require a lot of memory copying and handle resizing in their 
  1758. construction; this means that large AppleEvents may be slow in 
  1759. construction, especially when compared to a pure PPC Toolbox or 
  1760. ADSP/ASDSP link.  The way around this is to use Jens Alfke's AEGizmos, 
  1761. available on the Developer CD, to create AppleEvents.  AEGizmos are 
  1762. being integrated into System Software, so You Will be doing the right 
  1763. thing.
  1764.  
  1765. You should use your own application signature as event class for 
  1766. AppleEvents you make up, in order not to collide with anybody else.  
  1767. Other than that, you are free to make your own events for your own 
  1768. needs, though supporting the required events and at least a subset of 
  1769. the Core event suite will buy you a lot of functinality from within 
  1770. AppleScript.  Especially important are the Get Current Selection and Set 
  1771. Current Selection events (which are really Get/Set Data on the contents 
  1772. of the current selection of the application)
  1773.  
  1774. The signature for your application SHOULD be registered with DTS to 
  1775. avoid conflicts; this is done through e-mail to 
  1776. DEVSUPPORT@AppleLink.Apple.Com and the form you use is located on the 
  1777. developer CDs and found on ftp.apple.com.
  1778.  
  1779. 8.4) Q: How do AppleEvents interface with AppleScript? 
  1780.  
  1781. A: AppleEvents are the meat and potatoes of AppleScript.  If you support 
  1782. the AppleEvent Object Model from within your application, users can 
  1783. control you through AppleScript.
  1784.  
  1785. The first thing you should do is get ahold of Inside Mac: 
  1786. Interapplication Communication, and a copy of the AppleEvents Registry.  
  1787. The former tells you all you ever need to know about AppleEvents, while 
  1788. the latter is paramount for implementing the right standard events.  If 
  1789. everybody use the standard events, dynamic data interchange between any 
  1790. applications will become sweet reality!
  1791.  
  1792. Then there is the 'aete' resource which lets you put names on the events 
  1793. you support, so that users can "Open Terminology" on your application 
  1794. from within the Apple Script Editor and use the proper AppleScript 
  1795. commands in their scripts.  The format of an aete resource is defined in 
  1796. Inside Macintosh: Interapplication Communication.
  1797.  
  1798. 8.5) Q: Can I compile and run scripts from within my application?
  1799.  
  1800. A: Yes, this is very simple.  There are toolbox calls for reading 
  1801. scripts, compiling scripts, and executing scripts.  (OSACompile, 
  1802. OSAExecute) These are all documented in Inside Mac: Interapplication 
  1803. Communication.
  1804.  
  1805. 8.6) Q: Is this a good way of getting a macro language almost 
  1806. for free? 
  1807.  
  1808. A: "Good" is an understatement.  Just let users write scripts, load them 
  1809. into menu items and go.  Total systems integration in under a week, 
  1810. including adding support for the AEOM to your application.
  1811.  
  1812. There is source code for an application called "MenuScripter" on the 
  1813. developer CD which shows you how to do an application with all of the 
  1814. menus being AppleScript scripts.  
  1815.  
  1816. 8.7) Q: Why do I get error -903 (noPortErr) when I try to send an Apple 
  1817. Event?
  1818.  
  1819. A: Make sure the isHighLevelEventAware flag in your application's SIZE 
  1820. resource is set.  The AE Manager won't allow you to send events if you're 
  1821. not able to receive them.
  1822.  
  1823. *9* Standalone Code & Trap Patching
  1824.  
  1825. 9.1) Q: How do I do code resources/extensions/external functions, much 
  1826. like HyperCard XCMDs only for my 68k app/extension?
  1827.  
  1828. A: Here is what you need to do:
  1829.  
  1830. Define a storage location for the plug-ins.  such as, for an application 
  1831. called Foo, a folder called "Foo Pouch/ PlugIns/ Modules/ Tools/ Etc", 
  1832. which your installer creates, and which you search for in the same 
  1833. folder as your application, the preferences folder, and the System 
  1834. Folder (for System 6 (no preferences)) the name of the pouch folder 
  1835. should be in a 'STR ' or 'STR#' resource for easy internationalization.
  1836.  
  1837. Next, define a resource type to hold your plug-in exectuable code.  You 
  1838. should allow any resID number, since some development systems have 
  1839. restrictions on which id numbers can be used for multi-segment code 
  1840. resources.
  1841.  
  1842. Decide whether you will allow multiple code resources per file.  For 
  1843. example, Photoshop lets you bundle an import resource, an export 
  1844. resource, and a filter into the same file, each is its own resource 
  1845. type.  It uses the resource name to tell the user, so each has its own 
  1846. name.
  1847.  
  1848. Decide on the user interface to plug-ins.  Commonly, at program 
  1849. start-up, you scan the pouch and collect all the files of the correct 
  1850. types.  Then you scan for appropriate code resources, then put the names 
  1851. of the resources in the menus.  You can also use the file names, or run 
  1852. the code resources and ask them for the correct name.
  1853.  
  1854. Decide on the calling convention.  MPW likes to pass parameters as 
  1855. longs, and pascal development systems usually can't generate C 
  1856. interfaces, so your best bet is to have the entry point of your code 
  1857. resource be something like:
  1858.  
  1859. extern pascal long PlugIn(long selector, CallbackPtr callback,
  1860.         long param1, long param2, long param3, long refcon);
  1861.  
  1862. where params 1 through 3 will have specific meanings depending upon
  1863. which function selector is asking to be performed.
  1864.  
  1865. CallbackPtr is something like this:
  1866. typedef struct CallbackRec{
  1867.         DrawFunc        erase;
  1868.         DrawFunc        paint;
  1869. }CallbackRec, *CallbackPtr;
  1870.  
  1871. where DrawFunc is something like:
  1872. typedef pascal void (*DrawFunc)(Rect *);
  1873.  
  1874. This is the place where you define services that your application will 
  1875. perform when asked to by the code resource of the plug-in.
  1876.  
  1877. You'll need to define a bunch of selectors for what you want the plug-in
  1878. to do.
  1879.  
  1880. You should definately give the plug-in an Init selector, and a dispose 
  1881. selector, and have Init return an error or a refcon, which will be 
  1882. passed back to the plug-in on each call, so the plug-in can have some 
  1883. persistent storage.  You should definately set the CurResFile to the 
  1884. plug-in's file while it is running, so it can easily get at any 
  1885. resources it needs.
  1886.  
  1887. The Init selector should pass the interface version in param1 and the 
  1888. program version in param2, so that the plug-in can cope with different 
  1889. versions of your program.
  1890.  
  1891. The actual call to the plug-in looks like:
  1892.  
  1893. *code*
  1894.     h = GetResource('PLUG', 1);
  1895.     HLock(h);
  1896.     xh = StripAddress(h);
  1897.     ((PlugInFunc) *xh)(kInit, callbacks, kInterfaceVer1, kProgVer1, 0, 0);
  1898.     HUnlock(h);
  1899. *end*
  1900.  
  1901. The StripAddress is important; if your app is running in 24bit mode, the 
  1902. resource handle may contain tag bits and you don't want strange things 
  1903. to happen if the code resource switches into 32bit mode (which QuickDraw 
  1904. may do, incidentally)
  1905.  
  1906. Exactly how you structure your calling conventions is up to you; there 
  1907. is no accepted standard (except for HyperCard XCMDs, but that is 
  1908. probably overkill for you).
  1909.  
  1910. 9.2) Q: How do I fat-patch a trap (that is, how do I patch a trap with 
  1911. both 68k and PPC code)?
  1912.  
  1913. A: Create a normal fat routine descriptor and pass it to 
  1914. Set{Tool, OS}TrapAddress().
  1915.  
  1916. *10* Compatibility
  1917.  
  1918. 10.1) Q: I see all these people call Gestalt without first 
  1919. checking whether it's implemented. Isn't that bad? 
  1920.  
  1921. A: No; Gestalt and a few other traps (the HXxx file manager 
  1922. traps, and FindFolder) are implemented using glue so they do the 
  1923. right thing even if the trap is not implemented. 
  1924.  
  1925. If you want to get rid of the glue, you can #define 
  1926. SystemSevenOrLater (and, using Think C/C++, re-pre-compile 
  1927. MacHeaders) However, then you will be responsible for checking 
  1928. for these features before you use them. 
  1929.  
  1930. 10.2) Q: What more functions are implemented in glue? 
  1931.  
  1932. A: Wake Up and Smell the Glue!
  1933.  
  1934. How often have you wished you could use that cool new ToolBox 
  1935. call, but didn't want to make your application System 7 
  1936. dependent? Well, it might be that you *could* in fact have used 
  1937. the call. Several traps are implemented in glue, that is, much 
  1938. of their functionality is linked into your application and thus 
  1939. available even if you are running under an old System. 
  1940.  
  1941. This list applies to MPW 3.2 and should also be valid for the 
  1942. current version of Think C. If you find any inaccuracies, please 
  1943. report them to me. (neeri@iis.ee.ethz.ch) 
  1944.  
  1945. FSOpen: Tries first OpenDF, then Open. 
  1946.  
  1947. HOpenResFile: Full functionality emulated if trap not available 
  1948.  
  1949. HCreateResFile: Full functionality emulated if trap not 
  1950. available 
  1951.  
  1952. FindFolder: Under System 6, understands the following values for 
  1953. folderType and returns the System Folder for all of them: 
  1954.  
  1955. kAppleMenuFolderType 
  1956.  
  1957. kControlPanelFolderType 
  1958.  
  1959. kExtensionFolderType 
  1960.  
  1961. kPreferencesFolderType 
  1962.  
  1963. kPrintMonitorDocsFolderType 
  1964.  
  1965. kStartupFolderType 
  1966.  
  1967. kSystemFolderType 
  1968.  
  1969. kTemporaryFolderType 
  1970.  
  1971. SysEnvirons: Full functionality emulated if trap not available 
  1972.  
  1973. NewGestalt: Returns an error if not implemented 
  1974.  
  1975. ReplaceGestalt: Returns an error if not implemented 
  1976.  
  1977. Gestalt: The following selectors are always implemented: 
  1978.  
  1979. vers    mach    sysv    proc    fpu     
  1980.  
  1981. qd      kbd     atlk    ram     lram    
  1982.  
  1983. 10.3) Q: I have to support System 6, don't I? 
  1984.  
  1985. A: It would be foolish to lock yourself out of the many benefits 
  1986. the System 7 API provides for software that you start to write 
  1987. now. Some of the System 6 and older things (likely SFGetFile and 
  1988. wdRefNums among others) will be phased out of the interfaces and 
  1989. lose support; especially on future platforms. 
  1990.  
  1991. The installed base of System 7 is larger than that of System 6; 
  1992. this is not surprising because Apple has been shipping System 7 
  1993. for several years with all new machines, including the LCII, 
  1994. Classic II, Performas and Color Classic. Another argument is 
  1995. that newer computer owners (having System 7) are much more 
  1996. likely to buy new software than old computer owners who have 
  1997. systems that already do what they want them to. 
  1998.  
  1999. The added work to support both System 6 and System 7 is 
  2000. significant; if you have the time and money you may want to do 
  2001. it, but only supporting System 6 and not System 7 is doomed to 
  2002. fail in the market of today. 
  2003.  
  2004. Some may call this position subjective; I call it business sense 
  2005. based on market demographics. A rule of thumb may be that if you 
  2006. target color machines only, you can just as well demand System 7 
  2007. as well. 
  2008.  
  2009. 10.4) Q: Why does my application work on an SE with accellerator 
  2010. (or a Mac II or Quadra), but not on one without? 
  2011.  
  2012. A: Assuming you're not calling Color QuickDraw (which is not 
  2013. available on accellerated SEs), you most probably have an 
  2014. odd-aligned word access somewhere. 
  2015.  
  2016. The 68000 does not allow words or longwords to be read from odd 
  2017. addresses, while the 68020 and up relaxes this restriction (it 
  2018. still is slower than aligned-word access though) 
  2019.  
  2020. This may or may not crash depending on your compiler: 
  2021.  
  2022. *code*
  2023. struct foo {
  2024.     char c1 ;
  2025.     char c2 ;
  2026.     char c3 ;
  2027.     char c4 ;
  2028.     char c5 ;
  2029. } bar ;
  2030.  
  2031.     long * x = ( long * ) & bar . c2 ;
  2032.     * x = 0x12345678 ; /* X is odd if compiler doesn't pad */
  2033.  
  2034. This WILL crash on an SE/Plus/Classic/PB100:
  2035.  
  2036. char foo [ 10 ] ;
  2037.  
  2038.     long * x = ( long * ) & foo [ 1 ] ;
  2039.     * x = 0x12345678 ;
  2040.  
  2041. *end*
  2042.  
  2043. 10.5) Q: Why does my application work on a IIci and a pre-1995 PowerMac 
  2044. but not on a Quadra?
  2045.  
  2046. A: Two reasons: 
  2047.  
  2048. 1) The Quadras 900 and 950 have special processors that handle the serial 
  2049. ports; if you write directly to the serial chips, you will crash (this 
  2050. goes for the IIfx as well)
  2051.  
  2052. 2) The Quadras have 68040 processors, as have the Centrises.  These 
  2053. processors have separate instruction and data caches (like the 68030) but 
  2054. they are larger (4K each) and unlike the 68030 which is write-through 
  2055. data cached, the 68040 is copy-back data cached.  This means that changes 
  2056. you make to "your code" aren't really changed all the time, since the 
  2057. changes may still be in the data cache and not written to memory when the 
  2058. CPU reads that part of memory into its I-cache.  Even worse; that part 
  2059. might already have been read into the I-cache before you change it in the 
  2060. D-cache, meaning that writing out the D-cache will still not be enough.  
  2061. You need to flush both the caches when writing self-modifying code.
  2062.  
  2063. Self-modifying code includes code that builds its own jump tables and 
  2064. code that decrypts itself and code that "stubs" MDEFs or WDEFs to jump 
  2065. back into the application code.
  2066.  
  2067. You flush the cache using FlushDataCache() which is implemented if 
  2068. Gestalt says you have a 68020 or better processor (or if the _HwDispatch 
  2069. trap is implemented)
  2070.  
  2071. The current PowerMac 68k emulator doesn't have the self-modifying cache 
  2072. problem, but a future faster version will.
  2073.  
  2074. 10.6) Q: Why does my application work on my Quadra but not on my 
  2075. accellerated SE?
  2076.  
  2077. A: You're probably calling Color QuickDraw without first checking if it's 
  2078. available.  The following machines do not have color QuickDraw in ROM nor 
  2079. RAM:
  2080.  
  2081. Mac Plus, Mac SE, Mac Classic, Mac Luggable, PowerBook 100, Outbound
  2082.  
  2083. 10.7) Q: I do check for color quickdraw, but crash nevertheless. 
  2084.  
  2085. A: _Gestalt lies under some versions of System 7; it says that non-color 
  2086. machines HAVE color QuickDraw when you test using the 
  2087. gestaltQuickdrawFeatures selector.
  2088.  
  2089. Instead, check the gestaltQuickdrawVersion selector, if it returns >= 
  2090. gestalt8BitQuickdraw then you can safely use gestaltQuickdrawFeatures, 
  2091. else you only have b/w QuickDraw.
  2092.  
  2093. *11* Optional System Software
  2094.  
  2095.   *11.1* QuickTime
  2096.  
  2097. 11.1.1) Q: I want to write a Amiga QuickTime player and need the 
  2098. CODEC format details. 
  2099.  
  2100. A: Although the structure of QuickTime movies is well documented in 
  2101. Inside Mac: QuickTime, the inner workings of the Apple compression 
  2102. modules is a trade secret that Apple will only license to you at great 
  2103. cost.  Perhaps it's time for a freeware, cross-platform QuickTime codec?
  2104.  
  2105. *12* Third-Party Solutions
  2106.  
  2107.   *12.1* Databases
  2108.  
  2109. 12.1.1) Q: What are some royalty-free databases available for the 
  2110. Macintosh?
  2111.  
  2112. A: These are commercial with no run-time licenses:
  2113.  
  2114. - Prograph CPX comes with a database that can do indexes and tables.  
  2115. <sales@prograph.com>
  2116.  
  2117. - CXBase Pro is an engine that comes with source, does tables and indexes 
  2118. in one compound file.  <tse.int@applelink.apple.com>
  2119.  
  2120. - dtF is a relational database library.  <DTF.AMERICA@applelink.apple.com>
  2121.  
  2122. NeoAccess is an object-oriented database, where you can store objects and 
  2123. retrieve by field value; it handles inheritance as well.  Comes as a 
  2124. demo on the CodeWarrior CD with an unlockable archive of the real thing.
  2125.  
  2126. 12.1.2) Q: I need a robust Client/Server database library.  What do I do?
  2127.  
  2128. A: Get the Macintosh Client/Server Database Development Summary, by Liam 
  2129. Breck.  It covers software applicable to Macintosh (and cross-platform) 
  2130. client/server database development in three categories:
  2131.  
  2132.   + Client application development tools
  2133.   + Data access layers
  2134.   + Database servers
  2135.  
  2136. The eight page (20 Kbytes ASCII text) document includes explanations of the
  2137. three categories and describes over 30 products. Its sources are vendors'
  2138. product literature, industry periodicals, and discussions with users and
  2139. vendors' tech support staff. It is purely informational and contains no
  2140. propaganda, as the author is a neutral party.
  2141.  
  2142. To receive a copy electronically, email a request to: 
  2143. <maccsdb@external.umass.edu>.  Tell 'em the Mac Programming FAQ sent 
  2144. you!
  2145.  
  2146.    *12.2* Circumvention of Toolbox Limitations
  2147.  
  2148. 12.2.1) Q: Help!  The List Manager is driving me right UP THE WALL!  I 
  2149. want to throw it out and start over.  What'r my options?
  2150.  
  2151. A: The only non-framework List Manager replacement of which I'm aware is 
  2152. StoneTable, a commerical replacement library for the List Manager which 
  2153. provides many extensions including variable size columns/rows, 
  2154. column/row titles, different style/font/size/color per cell, sorting, 
  2155. edit in cell, and much more. <http://www.teleport.com/~stack>
  2156.  
  2157. TCL, PowerPlant, and MacApp all have their own integrated list 
  2158. management solutions.
  2159.  
  2160. *13* Dessert
  2161.  
  2162. 13.1) Q: Dessert? 
  2163.  
  2164. A: Honey Hill Farms Cookie Jar Frozen Yoghurt or Haagen-Dazs Raspberry & 
  2165. Cream Ice Cream.
  2166.  
  2167. Hokey-Pokey icecream with chocolate sauce and (for those who like their 
  2168. brain food firmer) Almond and Double Chocolate CookieTime cookies!?
  2169.  
  2170. *14* Contributors
  2171.  
  2172. [do let me know if I've forgotten you]
  2173.  
  2174. Denis Birnie
  2175. Liam Breck
  2176. Scott Bronson <urge@mcl.mcl.ucsb.edu>
  2177. Tim Converse <converse@cs.uchicago.edu>
  2178. Bob Hablutzel
  2179. Julian Harris
  2180. Bruce Hoult <Bruce@hoult.actrix.gen.nz>
  2181. Peter Jensen <pjensen@netcom.com>
  2182. Steve Jasik <macnosy@jasik.com>
  2183. Jonathan Kimmitt <jrrk@camcon.co.uk>
  2184. Matthias Neeracher <neeri@iis.ee.ethz.ch>
  2185. David P. Oster <oster@netcom.com>
  2186. Louis M. Pecora
  2187. Ingemar Ragnemalm <ingemar@lysator.liu.se>
  2188. Pete Resnick <resnick@uiuc.edu>
  2189. Phil Shapiro <phils@bedford.symantec.com>
  2190. eric slosser <slosser@apple.com>
  2191. M Sooriarachchi
  2192. Bill <stack@teleport.com>
  2193. Chris Thomas <thunderone@delphi.com>
  2194. Doug W. <dougw@as.arizona.edu>
  2195. Jon Watte <h+@austin.metrowerks.com>
  2196. Rick Zaccone <zaccone@bucknell.edu>
  2197.  
  2198. -- 
  2199.  -- Jon W{tte, h+@nada.kth.se, Mac Software Engineer Deluxe --
  2200.  
  2201.    There's no problem that can't be solved using brute-force algorithms
  2202.    and a sufficiently fast computer. Ergo, buy more hardware.    (NOT!)
  2203.