Preamble
Source code from the second edition of Macintosh Programming Secrets (1992) by Scott Knaster
See also
- Source code for Symantec C++ Programming for Macintosh (1994)
- Source code for Macintosh C Programming Primer (1992)
- Source code for Macintosh Programming Techniques
- Source code for Macintosh Programming Secrets – Second Edition (1992)
- Source code for Macintosh Programming Secrets – First Edition (1988)
- Source code from Programmers Guide to MPW (1990)
- Other
Errata
MPW
- Source code from Programmers Guide to MPW (1990)
- Errata -Programmers Guide to MPW (1990)
- MPW stuff
- Building a “hello, world!” program using MPW – Reproduction steps
Links
- greenonline/Code_from_Macintosh_Programming_Secrets_1992
Notes
Chapter 3 – Getting the skeleton to work in MPW
Getting the skeleton to compile/build in MPW 3.2.3…
From the second edition, Listing 3-1 Standard_stuff.c
and StandardStuff.h
Apart from the numerous typos in the text, which are fixed in the full listing at the end of the chapter…
Some header files are actually required that aren’t mentioned:
- For
EventRecord
,
#include "Events.h"
- For
TrapTypes
(from Sleuthing the New System File)
#include <OSUtils.h> /* for GetTrapAddress() */
For inGrow
and other Window events
#include "Windows.h"
- For
MenuHandle
,
#include "Menus.h"
- For
Str255
,short
, etc.,
#include "Types.h"
- For
MAXLONG
,
#include "Values.h"
- For
NIL
,FALSE
,TRUE
,- StdDef.h has
NULL
- StdLib.h has
NULL
- AppleEvents.h has
true
,fals
, andnil
in lower case - MPW 3.2.3 seems to be missing
MacTypes.h
, which is here: jduerstock/mpw-headers/MacTypes.h, but there is an issue with LF/CR formatting in the downloaded ZIP, and copy/paste into BasiliskII doesn’t work (for whatever reason). - MPW 3.5 does have
MacTypes.h
, which also requiresConditionalMacros.h
. However, there are some issues of “Enum ID previously declared” - NOTE: Changing to lower case solves the issue for
nil
,true
, andfalse
. or just add the following#define
lines:
- StdDef.h has
#define TRUE true #define FALSE false #define NIL nil
It will now compile successfully!
Note, for NIL
, we could also have defined instead (which is a common thing to do):
#define NIL 0L
However, it won’t build as we are still missing some header files… such as for TE, Dialogs, Disk and System, and so on…
Add the following
/* Stuff for building */ #include "TextEdit.h" #include "Dialogs.h" #include "DiskInit.h" //#include "Disks.h" #include "Files.h" #include "Fonts.h" #include "Desk.h" //#include "Windows.h" //#include "StandardFile.h" //#include "OSEvents.h" //#include "OSUtils.h" //#include "Packages.h" //#include "Processes.h" //#include "QuickDraw.h"
Gets the errors down to just 4
# case diskEvt: # HandleDiskEvent(event); # ? ### Warning 236 Calling function that has no definition #-------------------------------------------------------------------------------------------------------------------------------- File "Standard_stuff.c"; Line 151 #-------------------------------------------------------------------------------------------------------------------------------- # if (TrackGoAway(theWindow, event->where)){ # CloseAnyWindow(FrontWindow()); # ? ### Warning 236 Calling function that has no definition #-------------------------------------------------------------------------------------------------------------------------------- File "Standard_stuff.c"; Line 232 #-------------------------------------------------------------------------------------------------------------------------------- # SetCursor(&qd.arrow); # GetIndString(&theMessage, 128, errNumber); # ? ### Warning 236 Calling function that has no definition #-------------------------------------------------------------------------------------------------------------------------------- File "Standard_stuff.c"; Line 370 #-------------------------------------------------------------------------------------------------------------------------------- #{ # if (NGetTrapAddress(0xA86E, ToolTrap) == NGEtTrapAddress(0xAA6E, ToolTrap)) # ? ### Warning 236 Calling function that has no definition #-------------------------------------------------------------------------------------------------------------------------------- File "Standard_stuff.c"; Line 438 #--------------------------------------------------------------------------------------------------------------------------------
blah
Next steps
HandleDiskEvent
isn’t in any of the MPW header files (at least not from jduerstock/mpw-headers/)
Two of these are typos on my part:
HandleDiskEvent
should beHandleDiskInsert
NGEtTrapAddress
should beNGetTrapAddress
In HandleMouseDown()
there is a disparity between the code in the explanatory text and the listing at the end of the chapter. The text shows:
case inGoAway: if (TrackGoAway(theWindow, event->where)){ CloseAnyWindow(FrontWindow()); } break;
but the complete listing uses theWindow
, which presumably comes from FindWindow()
call:
case inGoAway: if (TrackGoAway(theWindow, event->where)){ /*CloseAnyWindow(FrontWindow());*/ CloseAnyWindow(theWindow); } break;
However, the same “Calling function that has no definition” error appears. Again searching the MPW headers shows nothing, nor does a google search, apart from:
- Can’t Stop Procedure window from opening automatically along with db,
- Issue with ‘Find Peaks’ plugin when used in a loop
which aren’t Macintosh C related.
FindIndString()
to the contrary, has a number of references:
- Connecting A 68k Object File To PowerPC Code
- May require Code Fragment Manager or Mixed Mode and/or maybe
#include <ConditionalMacros.h>
,#include <MixedMode.h>
- May require Code Fragment Manager or Mixed Mode and/or maybe
- GetIndString(IM: Tx) – Inside Macintosh
- IM: More Macintosh Toolbox
After an actual “physical” search of the MPW3.2.3 directory, using the search tool in OSX/macOS/MacOS (or whatever it is called these days), GetIndString
is declared in ToolUtils.h
. So add
#include "ToolUtils.h"
That leaves just the CloseAnyWindow()
issue!
# 11:01:47 PM ----- Build of StandardStuff. # 11:01:47 PM ----- Analyzing dependencies. # 11:01:47 PM ----- Executing build commands. C -r Standard_stuff.c ### Warning 254 Local variable "mouse" not used within the Body of the function : MainEventLoop #-------------------------------------------------------------------------------------------------------------------------------- File "Standard_stuff.c"; Line 137 #-------------------------------------------------------------------------------------------------------------------------------- # if (TrackGoAway(theWindow, event->where)){ # CloseAnyWindow(FrontWindow()); # ? ### Warning 236 Calling function that has no definition #-------------------------------------------------------------------------------------------------------------------------------- File "Standard_stuff.c"; Line 236 #-------------------------------------------------------------------------------------------------------------------------------- Link -t APPL -c '????' Standard_stuff.c.o "MPW_3.2.3:MPW_3.2.3:MPW_Update:MPW_3.2.3:Libraries:CLibraries:"CSANELib.o "MPW_3.2.3:MPW_3.2.3:MPW_Update:MPW_3.2.3:Libraries:CLibraries:"Math.o "MPW_3.2.3:MPW_3.2.3:MPW_Update:MPW_3.2.3:Libraries:CLibraries:"StdClib.o "MPW_3.2.3:MPW_3.2.3:MPW_Update:MPW_3.2.3:Libraries:Libraries:"Runtime.o "MPW_3.2.3:MPW_3.2.3:MPW_Update:MPW_3.2.3:Libraries:Libraries:"Interface.o -o StandardStuff ### Link: Error: Undefined entry, name: (Error 28) "CloseAnyWindow" Referenced from: HandleMouseDown in file: Standard_stuff.c.o ### Link: Errors prevented normal completion. ### MPW Shell - Execution of StandardStuff.makeout terminated. ### MPW Shell - Execution of BuildProgram terminated.
A similar “physical” text in OSX for CloseAnyWindow
doesn’t reveal its location. Maybe it is a header in MPW 3.5?
In AppearenceSampleMain.c
, in MPW-GM/MPW3.5/EWxampes/CarbonExamples/AppearenceSample/AppearenceSampleMain.c
, there is the following “user defined” code
//——————————————————————————————————————————————————————————————————————————— // • CloseAnyWindow //——————————————————————————————————————————————————————————————————————————— // Close the given window in a manner appropriate for that window. If the // window belongs to a DA, we call CloseDeakAcc. For dialogs, we simply hide // the window. If we had any document windows, we would probably call either // DisposeWindow or CloseWindow after disposing of any document data and/or // controls. // static void CloseAnyWindow( WindowPtr window ) { BaseWindow* wind; if ( IsDAWindow( window ) ) { // CloseDeskAcc( ((WindowPeek)window)->windowKind ); } else if ( GetObjectFromWindow( window, &wind ) ) { delete wind; } else DisposeWindow( window ); }
Upon a closer look, any mention of CloseAnyWindow
is missing from the text of the book (including the summary of the routines) – although it is present in both the listing 3-1 and listing 3-2 at the end of the chapter)! So, never trust the text and only follow the listings – is that the lesson to be learnt here?
/******************************************************************************** CloseAnyWindow Close the given window in an manner appropriate for that window. If the window belongs to a DA, we call CloseDeskAcc. For dialogs, we simply hide the window. If we had any document windows, we would probably call either DisposeWindow or CloseWindow after disposing of any document data and/or controls. ********************************************************************************/ void CloseAnyWindow(WindowPtr window) { if (IsDAWindow(window)) { CloseDeskAcc(((WindowPeek) window) ->windowKind); } else if (IsDialogWindow(window)) { HideWindow(window); } else if (IsAppWindow(window)) { /* Do something significant for document windows. */ } }
Then after that has been entered, the build complains that IsDialogWindow
is missing. It is the same story (missing from the text, but is given in the listing(s)
/******************************************************************************** IsDialogWindow Check to see if a window is a dialog window. We can determine this by checking to see if the windowKind field is equal to dialogKind. ********************************************************************************/ Boolean IsDialogWindow(WindowPtr window) { if (window==NIL) return FALSE; else return (((WindowPeek)window)->windowKind == dialogKind); }
Finally success!
# 11:50:41 PM ----- Build of StandardStuff. # 11:50:41 PM ----- Analyzing dependencies. # 11:50:42 PM ----- Executing build commands. C -r Standard_stuff.c ### Warning 254 Local variable "mouse" not used within the Body of the function : MainEventLoop #-------------------------------------------------------------------------------------------------------------------------------- File "Standard_stuff.c"; Line 137 #-------------------------------------------------------------------------------------------------------------------------------- Link -t APPL -c '????' Standard_stuff.c.o "MPW_3.2.3:MPW_3.2.3:MPW_Update:MPW_3.2.3:Libraries:CLibraries:"CSANELib.o "MPW_3.2.3:MPW_3.2.3:MPW_Update:MPW_3.2.3:Libraries:CLibraries:"Math.o "MPW_3.2.3:MPW_3.2.3:MPW_Update:MPW_3.2.3:Libraries:CLibraries:"StdClib.o "MPW_3.2.3:MPW_3.2.3:MPW_Update:MPW_3.2.3:Libraries:Libraries:"Runtime.o "MPW_3.2.3:MPW_3.2.3:MPW_Update:MPW_3.2.3:Libraries:Libraries:"Interface.o -o StandardStuff ### Link: Warning: File was not needed for link: (Error 52) MPW_3.2.3:MPW_3.2.3:MPW_Update:MPW_3.2.3:Libraries:CLibraries:CSANELib.o ### Link: Warning: File was not needed for link: (Error 52) MPW_3.2.3:MPW_3.2.3:MPW_Update:MPW_3.2.3:Libraries:CLibraries:Math.o ### Link: Warning: File was not needed for link: (Error 52) MPW_3.2.3:MPW_3.2.3:MPW_Update:MPW_3.2.3:Libraries:CLibraries:StdClib.o # 11:50:44 PM ----- Done. StandardStuff
Chapter 3 – Getting the skeleton to work in Think C
Continuing where we left off in MPW, but continuing in ThinkC… this is a lot easier. However, what is strange is that a few typos were detected in ThinkC than MPW seemed to ignore and compiled and built an application anyway (albeit that the application didn’t work, ewith error -192 or the application just opened and quit immediately (crashed?)).
After fixing the typos, and then running, the application still quits immediately (crashes). After some thought, I realised it is because no resource file is provided. Looking at the code, only four resources are required, one MBAR (128) linking the three MENU resources (128, 129 and 130) for the Apple, File and Edit menus. Their items can be deduced from the StandardStuff.h file.
Once the resource file is made then the application runs perfectly..! This .res
file might work (untested)
/* StandardStuff.h */ /* Taken from Creation.r from Programmers Guide to MPW */ #include "Types.r"; #include "SysTypes.r" #include "StandardStuff.h" resource 'MBAR' (rMenuBar, preload) { { mApple, mFile, mEdit }; }; resource 'MENU' (mApple, preload) { mApple, textMenuProc, 0b1111111111111111111111111111101, /* disable dashed line, */enabled, apple,/* enable About and DAs*/ { "About...", noicon, nokey, nomark, plain; "-", noicon, nokey, nomark, plain } }; resource 'MENU' (mFile, preload) { mFile, textMenuProc, 0b1111111111111111111101100001000, enabled, "File", { "New", noicon, "N", nomark, plain; "Open", noicon, "O", nomark, plain; "-", noicon, nokey, nomark, plain; "Close", noicon, "W", nomark, plain; "Save", noicon, "S", nomark, plain; "Save As...", noicon, nokey, nomark, plain; "Revert", noicon, nokey, nomark, plain; "-", noicon, nokey, nomark, plain; "Page Setup...", noicon, nokey, nomark, plain; "Print...", noicon, nokey, nomark, plain; "-", noicon, nokey, nomark, plain; "Quit", noicon, "Q", nomark, plain } }; resource 'MENU' (mEdit, preload) { mEdit, textMenuProc, 0b1111111111111111111111110111101, enabled, "Edit", { "Undo", noicon, "Z", nomark, plain; "-", noicon, nokey, nomark, plain; "Cut", noicon, "X", nomark, plain; "Copy", noicon, "C", nomark, plain; "Paste", noicon, "V", nomark, plain; "Clear", noicon, "B", nomark, plain; } }; resource 'SIZE' (-1) { /* MultiFinder-aware application */ dontSaveScreen, acceptSuspendResumeEvents, enableOptionSwitch, canBackground, multiFinderAware, backgroundAndForeground, dontGetFrontClicks, ignoreChildDiedEvents, not32BitCompatible, reserved, reserved, reserved, reserved, reserved, reserved, reserved, 96*1024, 64*1024 };
blah
Chapter 4
Changes to StandardStuff.c
See also (or move from) Errata – Macintosh Programming Secrets (1992), the section Guessing AdjustMenus()
.
- Need to
sleepyTime
, which is along
, solong sleepyTime;
is needed inMainEventLoop()
This is the end, my friend