by Niklas Nisbeth, 2023
Here is some text inspired by my excursions into programming for Mac OS 9 using the MacZoop framework. While my first initial stabs at programming where in fact done on Mac OS 9 (when it was current), I never got to writing a GUI app. I got a bit further on OS X with Cocoa, but the bulk of my programming experience has been first in a much more theoretical, computer sciency high-level style of programming in functional languages like Scheme and OCaml, and later as a professional programmer with an assortment of web-adjencent technologies as well as hobbyist level embedded programming in C. So these are also notes from someone who came from something much more modern making their first real attempts at understanding how the old Mac OS works on a technical level, and how software was written for it.
(Please note that this means I might write some stuff that's wrong or misunderstand - no warranty - no refunds)
MacZoop is an application framework for the pre-OS X Macintosh. That is to say, it was upgraded for the "Carbon" APIs that were a slightly updated edition of most of the old Macintosh APIs. I'm not interested in OS X, though, and thus not in Carbon, so I'm using the second-to-last version of the framework (version 2.5), which is from early 2001, just a few years before the official end of Mac OS 9.
I think I first heard of MacZoop because it was apparently used for the first versions of the SuperCollider audio programming language. The SuperCollider 2 code is not released, supposedly because the MacZoop license forbids redistribution of modified versions or something like that. Maybe someone should send some e-mails to see if that still holds, the old SuperCollider code would be fun to have. But I digress.
The King of the Mac Programming Hill from the mid-90's or so until the introduction of Mac OS X was Metroworks's PowerPlant framework. MacZoop isn't all that different to PowerPlant, except in one important parameter: weight. PowerPlant is a lot bigger, arguably more comprehensive, and comes with huge amounts of dry documentation, including two entire book-length tutorials. MacZoop is advertized as a framework "for the rest of us" and has a few hundred pages accompanying it, a combined tutorial, manual and class reference. For the rest I've just gone straight into the source code. I've attempted learning PowerPlant on one or two occasions, but this has been much more digestible to me.
MacZoop builds on top of the system APIs to provide a nicer way to write applications. It is written in C++ and heavily "object oriented" in the 90's way. I haven't seen any templates (did they even exist?) but there's a lot of subclassing and you're expected to write your own applications by making subclasses of the provided ZView, ZWindow classes etc. This is in stark contrast to how the NeXT-derived APIs for OS X favour delegation over subclassing - the classes you write contain instances of a window, they aren't windows themselves.
The other big difference to what I'm used it is that there's very little encouragement to do any sort of "separation of concerns". There's no mention of MVC or any sort of methodology. You subclass the window or view, and every action that your menus or buttons might effect is a numeric constant sent to the window's HandleCommand function, which then has a big switch statement. It's up to you to create utility functions or classes. If what you have is a single-window app, you totally can just write the entire application in your big switch. This is the 90's, after all.
And I have to be honest, here: at this point in time, for me in my career as a programmer who spends a lot of time during the day worrying about clean code and best pracises and all that, I find this extremely liberating and refreshing and it's exactly what I need for coding as a hobby and I'm going to run with it. But old Macs crash a lot for a reason.
This took some time. I had to find a version of the Mac "Universal Headers" that matches the MacZoop release I'm using, version 3.4. I may have made it more difficult for myself by using a version of Codewarrior (5) that's a little earlier than what MacZoop 2.5 was made with, I'm not sure, but anyway, the headers didn't match what MacZoop wanted. I had to put the headers in the right place so Codewarrior could see them and recompile the headers (I'm not sure what compiling headers means either, but there was a script to do it and then it working).
CodeWarrior 5 really likes spitting out lots of errors. A missing header isn't one error message, it's hundreds. My first attempts at compiling a MacZoop example gave me thousands of errors. It seems like missing definitions make it extremely confused about the syntax, so a function prototype that references an unknown class throws it off completely and it just doesn't like any of the code after that. I haven't done much modern C++, but it seems a lot worse and much more confusing than anything I've seen this century. But after understanding that that this was how it works, it became easier, if still a bit unwieldy.
MacZoop is distributed in source form and you're supposed to just include it into your project. I don't know if there's a technical or a cultural reason, but what I've seen in other places (like any desktop toolkit or framework on modern platforms), the framework is a dynamic library that you link against. Not here. You stick all the sources in your project in CodeWarrior and compile everything together. Again I can see why it's bad but I kind of like the simplicity of it. It's also meant that the source was easy to get at when I had problems understanding why something wasn't working, I could see what the framework was doing and work backwards from there.
This was the one thing that I really couldn't live with. There's no version control by default, no concept of checking something in and being able to go back beyond your undo history. I've basically never not used Git when coding, so this is completely alien. I was able to setup Codewarrior to use Apple's "Projector" VCS, but it's incredibly primitive. All commits and history are per-file, there's seemingly nothing like a project-wide "commit" in Git.
I wrote a dumb todolist like thing. You can add items to the list and cross them out by clicking on them. There's no resizing and no text wrapping or support for linebreaks,so you get 200 pixels to describe what is to be done. Should be enough, right?
Working on this was very fun and enlightening, but I don't know how far I'll take it. It's not really something I need. I hope to add more to this document, though, and release a working template for MacZoop and CW5 in case anyone else wants to join in.
April 8, 2023: Screenshot of MacTasks
March 27-28, 2023: Initial, incomplete version. Drafted on a G4 in BBEdit