OSDN Git Service

二倍幅表示の情報がきちんと保持されていなかったので修正。
[hengband/hengband.git] / src / main-mac.c
index 1a5c3d9..6d1870a 100644 (file)
 
 #include "angband.h"
 
+#ifdef MACH_O_CARBON
+
+#include <Carbon/Carbon.h>
+#include <QuickTime/QuickTime.h>
+#include <CoreServices/CoreServices.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+#define TARGET_API_MAC_CARBON 1
+
+#else /* MACH_O_CARBON */
+
 #include <Types.h>
 #include <Gestalt.h>
 #include <QuickDraw.h>
 #include <Sound.h>
 #if TARGET_API_MAC_CARBON
 #include <Navigation.h>
+#include <CFPreferences.h>
+#include <CFNumber.h>
 # ifdef MAC_MPW
 # include <CarbonStdCLib.h>
 # endif
 
 #endif
 
+#endif /* MACH_O_CARBON */
+
 /*
  * Cleaning up a couple of things to make these easier to change --AR
  */
 /* #define USE_MALLOC */
 
 
+/* Default creator signature */
+#ifndef ANGBAND_CREATOR
+# define ANGBAND_CREATOR 'Heng'
+#endif
+
+
 #if defined(powerc) || defined(__powerc)
 
 /*
  */
 # define USE_SFL_CODE
 
+/*
+ * Use rewritten asynchronous sound player
+ */
+#define USE_ASYNC_SOUND
+
+
+#ifdef MACH_O_CARBON
+
+#define USE_QT_SOUND
+
+#endif /* MACH_O_CARBON */
 #endif /* ANGBAND_LITE_MAC */
 
 
 
+#ifndef MACH_O_CARBON
 #ifdef USE_SFL_CODE
 
 /*
 #include <Folders.h>
 
 #endif
-
+#endif /* !MACH_O_CARBON */
 
 /*
  * Globals for MPW compilation
  */
 #if defined(MACH_O_CARBON) || defined(MAC_MPW)
        /* Globals needed */
+#if !TARGET_API_MAC_CARBON
+       QDGlobals qd;
+#endif
        OSType _ftype;
        OSType _fcreator;
 #endif
@@ -356,6 +392,7 @@ struct term_data
  */
 static bool CheckEvents(bool wait);
 
+#ifndef MACH_O_CARBON
 
 /*
  * Hack -- location of the main directory
@@ -363,6 +400,7 @@ static bool CheckEvents(bool wait);
 static short app_vol;
 static long  app_dir;
 
+#endif /* !MACH_O_CARBON */
 
 /*
  * Delay handling of double-clicked savefiles
@@ -406,11 +444,14 @@ static bool initialized = FALSE;
 static long mac_os_version;
 
 
+#if defined(__MWERKS__)
 /*
  * CodeWarrior uses Universal Procedure Pointers
  */
 static ModalFilterUPP ynfilterUPP;
 
+#endif /* __MWERKS__ */
+
 #ifdef USE_SFL_CODE
 
 /*
@@ -424,94 +465,6 @@ AEEventHandlerUPP AEH_Open_UPP;
 #endif
 
 /*
-       Extra Sound Mode
-*/
-
-static int ext_sound = 0;
-
-#define                SND_NON         0
-#define                SND_ATTACK      1
-#define                SND_MOVE                2
-#define                SND_TRAP                3
-#define                SND_SHOP                4
-#define                SND_ME          5
-#define                SND_CMD_ERROR   6
-
-static int soundchoice[] = {
-       SND_NON,
-       SND_ATTACK,
-       SND_ATTACK,
-       SND_ATTACK,
-       SND_TRAP,
-       SND_ATTACK,
-       SND_ME,
-       SND_ME,
-       SND_ME,
-       SND_MOVE,
-       SND_ATTACK,
-       SND_ME,
-       SND_ATTACK,
-       SND_NON,
-       SND_MOVE,
-       SND_MOVE,
-       SND_ME,
-       SND_SHOP,
-       SND_SHOP,
-       SND_SHOP,
-       SND_SHOP,
-       SND_MOVE,
-       SND_MOVE,
-       SND_MOVE,
-       SND_MOVE,
-       SND_ATTACK,
-       SND_SHOP,
-       SND_SHOP,
-       SND_ME,
-       SND_NON,
-       SND_ATTACK,
-       SND_NON,
-       SND_NON,
-       SND_NON,
-       SND_NON,
-       SND_ATTACK,
-       SND_ATTACK,
-       SND_NON,
-       SND_NON,
-       SND_ATTACK,
-       SND_NON,
-       SND_NON,
-       SND_NON,
-       SND_TRAP,
-       SND_ATTACK,
-       SND_ATTACK,
-       SND_ATTACK,
-       SND_ATTACK,
-       SND_ATTACK,
-       SND_NON,
-       SND_NON,
-       SND_NON,
-       SND_NON,
-       SND_NON,
-       SND_CMD_ERROR,
-       SND_TRAP,
-       SND_NON,
-       SND_NON,
-       SND_TRAP,
-       SND_ATTACK,
-       SND_TRAP,
-       SND_ATTACK,
-       SND_ATTACK,
-       SND_NON,
-       SND_TRAP,
-};
-
-static int                     soundmode[8];
-
-static int ext_graf = 0;
-
-
-
-/*
  * Convert refnum+vrefnum+fname into a full file name
  * Store this filename in 'buf' (make sure it is long enough)
  * Note that 'fname' looks to be a "pascal" string
@@ -520,7 +473,6 @@ static int ext_graf = 0;
 static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname)
 {
        CInfoPBRec pb;
-       Str255 name;
        int err;
        int i, j;
 
@@ -685,6 +637,7 @@ static bool askfor_file(char *buf, int len)
 
 #endif
 
+#if !TARGET_API_MAC_CARBON
 static void local_to_global( Rect *r )
 {
        Point           temp;
@@ -705,6 +658,7 @@ static void local_to_global( Rect *r )
        r->right = temp.h;
        r->bottom = temp.v;
 }
+#endif /* !TARGET_API_MAC_CARBON */
 
 static void global_to_local( Rect *r )
 {
@@ -860,6 +814,84 @@ static void center_rect(Rect *r, Rect *s)
 }
 
 
+#ifdef MACH_O_CARBON
+
+/* Carbon File Manager utilities by pelpel */
+
+/*
+ * (Carbon)
+ * Convert a pathname to a corresponding FSSpec.
+ * Returns noErr on success.
+ */
+static OSErr path_to_spec(const char *path, FSSpec *spec)
+{
+       OSErr err;
+       FSRef ref;
+
+       /* Convert pathname to FSRef ... */
+       err = FSPathMakeRef(path, &ref, NULL);
+       if (err != noErr) return (err);
+
+       /* ... then FSRef to FSSpec */
+       err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
+       
+       /* Inform caller of success or failure */
+       return (err);
+}
+
+
+/*
+ * (Carbon)
+ * Convert a FSSpec to a corresponding pathname.
+ * Returns noErr on success.
+ */
+static OSErr spec_to_path(const FSSpec *spec, char *buf, size_t size)
+{
+       OSErr err;
+       FSRef ref;
+
+       /* Convert FSSpec to FSRef ... */
+       err = FSpMakeFSRef(spec, &ref);
+       if (err != noErr) return (err);
+
+       /* ... then FSRef to pathname */
+       err = FSRefMakePath(&ref, buf, size);
+
+       /* Inform caller of success or failure */
+       return (err);
+}
+
+
+/*
+ * (Carbon) [via path_to_spec]
+ * Set creator and filetype of a file specified by POSIX-style pathname.
+ * Returns 0 on success, -1 in case of errors.
+ */
+void fsetfileinfo(cptr pathname, OSType fcreator, OSType ftype)
+{
+       OSErr err;
+       FSSpec spec;
+       FInfo info;
+
+       /* Convert pathname to FSSpec */
+       if (path_to_spec(pathname, &spec) != noErr) return;
+
+       /* Obtain current finder info of the file */
+       if (FSpGetFInfo(&spec, &info) != noErr) return;
+
+       /* Overwrite creator and type */
+       info.fdCreator = fcreator;
+       info.fdType = ftype;
+       err = FSpSetFInfo(&spec, &info);
+
+       /* Done */
+       return;
+}
+
+
+#else /* MACH_O_CARBON */
+
+
 /*
  * Convert a pascal string in place
  *
@@ -943,55 +975,7 @@ static void PathNameFromDirID(long dirID, short vRefNum, StringPtr fullPathName)
 }
 
 #endif
-
-#if TARGET_API_MAC_CARBON
-
-static OSErr ChooseFile( StringPtr filename, FSSpec selfld )
-{
-       NavReplyRecord          reply;
-       NavDialogOptions        dialogOptions;
-       NavTypeListHandle       navTypeList = NULL;
-       OSErr                           err;
-       AEDesc  deffld;
-       
-       AECreateDesc( typeFSS, &selfld, sizeof(FSSpec), &deffld );
-       
-       err = NavGetDefaultDialogOptions( &dialogOptions );
-       
-       if( err == noErr ){
-               
-               err = NavChooseFile( &deffld, &reply, &dialogOptions, NULL, NULL, NULL, navTypeList, NULL );
-               
-               if ( reply.validRecord && err == noErr ){
-                       // grab the target FSSpec from the AEDesc:
-                       FSSpec          finalFSSpec;
-                       AEKeyword       keyWord;
-                       DescType        typeCode;
-                       Size            actualSize = 0;
-
-                       // retrieve the returned selection:
-                       // there is only one selection here we get only the first AEDescList:
-                       if (( err = AEGetNthPtr( &(reply.selection), 1, typeFSS, &keyWord, &typeCode, &finalFSSpec, sizeof( FSSpec ), &actualSize )) == noErr )
-                       {
-                               refnum_to_name( (char *)filename, finalFSSpec.parID, finalFSSpec.vRefNum, (char *)finalFSSpec.name );
-                               // 'finalFSSpec' is the chosen file¥Î
-                       }
-                       
-                       err = NavDisposeReply( &reply );
-               }
-               if( navTypeList != NULL )
-               {
-                       DisposeHandle( (Handle)navTypeList );
-                       navTypeList = NULL;
-               }
-       }
-       
-       AEDisposeDesc( &deffld );
-       
-       return err;
-}
-
-#endif
+#endif /* MACH_O_CARBON */
 
 /*
  * Activate a given window, if necessary
@@ -1306,16 +1290,45 @@ static void term_data_redraw(term_data *td)
 
 
 /*
- * Constants
+ * Graphics support
+ */
+
+/*
+ * PICT id of image tiles, set by Term_xtra_mac_react
+ */
+#ifdef MACH_O_CARBON
+static CFStringRef pictID = NULL;
+#else
+static int pictID = 0;
+#endif /* MACH_O_CARBON */
+
+/*
+ * Width and height of a tile in pixels
+ */
+static int grafWidth = 0;
+static int grafHeight = 0;
+
+/*
+ * Numbers of rows and columns in tiles, calculated by
+ * the PICT loading code
  */
+static int pictCols = 0;
+static int pictRows = 0;
 
-static int pictID = 1001;      /* 8x8 tiles; 16x16 tiles are 1002 */
+/*
+ * Available graphics modes - 32x32 tiles don't work on Classic
+ */
+#define GRAF_MODE_NONE 0
+#define GRAF_MODE_8X8  1
+#define GRAF_MODE_16X16        2
+#define GRAF_MODE_32X32        3
 
-static int grafWidth = 8;      /* Always equal to grafHeight */
-static int grafHeight = 8;     /* Either 8 or 16 */
+/*
+ * Current and requested graphics modes
+ */
+static int graf_mode = GRAF_MODE_NONE;
+static int graf_mode_req = GRAF_MODE_NONE;
 
-static bool arg_newstyle_graphics;
-static bool use_newstyle_graphics;
 
 /*
  * Forward Declare
@@ -1379,6 +1392,123 @@ static void BenSWUnlockFrame(FrameRec *srcFrameP)
        
 }
 
+#ifdef MACH_O_CARBON
+
+/*
+ * Moving graphics resources into data fork -- pelpel
+ *
+ * (Carbon, Bundle)
+ * Given base and type names of a resource, find a file in the
+ * current application bundle and return its FSSpec in the third argument.
+ * Returns true on success, false otherwise.
+ * e.g. get_resource_spec(CFSTR("8x8"), CFSTR("png"), &spec);
+ */
+static Boolean get_resource_spec(
+       CFStringRef base_name, CFStringRef type_name, FSSpec *spec)
+{
+       CFURLRef res_url;
+       FSRef ref;
+
+       /* Find resource (=file) in the current bundle */
+       res_url = CFBundleCopyResourceURL(
+               CFBundleGetMainBundle(), base_name, type_name, NULL);
+
+       /* Oops */
+       if (res_url == NULL) return (false);
+
+       /* Convert CFURL to FSRef */
+       (void)CFURLGetFSRef(res_url, &ref);
+
+       /* Convert FSRef to FSSpec */
+       (void)FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
+
+       /* Free allocated CF data */
+       CFRelease(res_url);
+
+       /* Success */
+       return (true);
+}
+
+
+/*
+ * (QuickTime)
+ * Create a off-screen GWorld from contents of a file specified by a FSSpec.
+ * Based on BenSWCreateGWorldFromPict.
+ *
+ * Globals referenced: data[0], graf_height, graf_width
+ * Globals updated: pict_rows, pict_cols.
+ */
+static OSErr create_gworld_from_spec(
+       GWorldPtr *tile_gw, FSSpec *tile_spec)
+{
+       OSErr err;
+       GraphicsImportComponent gi;
+       GWorldPtr gw, tmp_gw;
+       GDHandle gdh, tmp_gdh;
+       Rect r;
+       SInt16 depth;
+
+       /* See if QuickTime understands the file format */
+       err = GetGraphicsImporterForFile(tile_spec, &gi);
+
+       /* Oops */
+       if (err != noErr) return (err);
+
+       /* Get depth */
+       depth = data[0].pixelDepth;
+
+       /* Get GDH */
+       gdh = data[0].theGDH;
+
+       /* Retrieve the rect of the image */
+       err = GraphicsImportGetNaturalBounds(gi, &r);
+
+       /* Adjust it, so that the upper left corner becomes (0, 0) */
+       OffsetRect(&r, -r.left, -r.top);
+
+       /* Calculate and set numbers of rows and columns */
+       pictRows = r.bottom / grafHeight;
+       pictCols = r.right / grafWidth;
+
+       /* Create a GWorld */
+       err = NewGWorld(&gw, depth, &r, NULL, gdh, noNewDevice);
+
+       /* Oops */
+       if (err != noErr) return (err);
+
+       /* Save the pointer to the GWorld */
+       *tile_gw = gw;
+
+       /* Save the current GWorld */
+       GetGWorld(&tmp_gw, &tmp_gdh);
+
+       /* Activate the newly created GWorld */
+       (void)GraphicsImportSetGWorld(gi, gw, NULL);
+
+       /* Prevent pixmap from moving while drawing */
+       (void)LockPixels(GetGWorldPixMap(gw));
+
+       /* Clear the pixels */
+       EraseRect(&r);
+
+       /* Draw the image into it */
+       (void)GraphicsImportDraw(gi);
+
+       /* Release the lock*/
+       UnlockPixels(GetGWorldPixMap(gw));
+
+       /* Restore GWorld */
+       SetGWorld(tmp_gw, tmp_gdh);
+
+       /* Close the image importer */
+       CloseComponent(gi);
+
+       /* Success */
+       return (noErr);
+}
+
+#else /* MACH_O_CARBON */
+
 static OSErr BenSWCreateGWorldFromPict(
        GWorldPtr *pictGWorld,
        PicHandle pictH)
@@ -1436,7 +1566,7 @@ static OSErr BenSWCreateGWorldFromPict(
        return (0);
 }
 
-
+#endif /* MACH_O_CARBON */
 
 
 /*
@@ -1449,7 +1579,11 @@ static errr globe_init(void)
        
        GWorldPtr tempPictGWorldP;
 
+#ifdef MACH_O_CARBON
+       FSSpec pict_spec;
+#else
        PicHandle newPictH;
+#endif /* MACH_O_CARBON */
 
        /* Use window XXX XXX XXX */
 #if TARGET_API_MAC_CARBON
@@ -1459,6 +1593,38 @@ static errr globe_init(void)
 #endif
 
 
+#ifdef MACH_O_CARBON
+
+       /* Get the tile resources */
+       if (!get_resource_spec(pictID, CFSTR("png"), &pict_spec)) return (-1);
+
+       /* Create GWorld */
+       err = create_gworld_from_spec(&tempPictGWorldP, &pict_spec);
+
+       /* Error */
+       if (err != noErr) return (err);
+
+       /* Create the frame */
+       frameP = (FrameRec*)NewPtrClear((Size)sizeof(FrameRec));
+
+       /* Analyze result */
+       if (frameP == NULL)
+       {
+               /* Dispose of image GWorld */
+               DisposeGWorld(tempPictGWorldP);
+
+               /* Fake error code */
+               return (-1);
+       }
+
+       /* Save GWorld */
+       frameP->framePort = tempPictGWorldP;
+
+       /* Lock it */
+       BenSWLockFrame(frameP);
+
+#else /* MACH_O_CARBON */
+
        /* Get the pict resource */
        newPictH = GetPicture(pictID);
 
@@ -1495,6 +1661,8 @@ static errr globe_init(void)
                        }
                }
        }
+#endif /* MACH_O_CARBON */
+
 
        /* Result */
        return (err);
@@ -1530,11 +1698,565 @@ static errr globe_nuke(void)
 }
 
 
-#endif /* ANGBAND_LITE_MAC */
+# ifdef USE_ASYNC_SOUND
 
+/*
+ * Asynchronous sound player revised
+ */
+#if defined(USE_QT_SOUND) && !defined(MACH_O_CARBON)
+# undef USE_QT_SOUND
+#endif /* USE_QT_SOUND && !MACH_O_CARBON */
 
 
-/*** Support for the "z-term.c" package ***/
+/*
+ * Number of channels in the channel pool
+ */
+#if TARGET_API_MAC_CARBON
+#define MAX_CHANNELS           8
+#else
+#define MAX_CHANNELS           4
+#endif
+
+/*
+ * A pool of sound channels
+ */
+static SndChannelPtr channels[MAX_CHANNELS];
+
+/*
+ * Status of the channel pool
+ */
+static Boolean channel_initialised = FALSE;
+
+/*
+ * Data handles containing sound samples
+ */
+static SndListHandle samples[SOUND_MAX];
+
+/*
+ * Reference counts of sound samples
+ */
+static SInt16 sample_refs[SOUND_MAX];
+
+
+/*
+ * Sound effects
+ *
+ * These constants aren't used by the program at the moment.
+ */
+#define SOUND_VOLUME_MIN       0       /* Default minimum sound volume */
+#define SOUND_VOLUME_MAX       255     /* Default maximum sound volume */
+#define VOLUME_MIN                     0       /* Minimum sound volume in % */
+#define VOLUME_MAX                     100     /* Maximum sound volume in % */
+#define VOLUME_INC                     5       /* Increment sound volume in % */
+
+/* I'm just too lazy to write a panel for this XXX XXX */
+static SInt16 sound_volume = SOUND_VOLUME_MAX;
+
+#ifdef USE_QT_SOUND
+
+/*
+ * QuickTime sound, by Ron Anderson
+ *
+ * I didn't choose to use Windows-style .ini files (Ron wrote a parser
+ * for it, but...), nor did I use lib/xtra directory, hoping someone
+ * would code plist-based configuration code in the future -- pelpel
+ */
+
+/*
+ * (QuickTime)
+ * Load sound effects from data-fork resources.  They are wav files
+ * with the same names as angband_sound_name[] (variable.c)
+ *
+ * Globals referenced: angband_sound_name[]
+ * Globals updated: samples[] (they can be *huge*)
+ */
+static void load_sounds(void)
+{
+       OSErr err;
+       int i;
+
+       /* Start QuickTime */
+       err = EnterMovies();
+
+       /* Error */
+       if (err != noErr) return;
+
+       /*
+        * This loop may take a while depending on the count and size of samples
+        * to load.
+        *
+        * We should use a progress dialog for this.
+        */
+       for (i = 1; i < SOUND_MAX; i++)
+       {
+               /* Apple APIs always give me headacke :( */
+               CFStringRef name;
+               FSSpec spec;
+               SInt16 file_id;
+               SInt16 res_id;
+               Str255 movie_name;
+               Movie movie;
+               Track track;
+               Handle h;
+               Boolean res;
+
+               /* Allocate CFString with the name of sound event to be processed */
+               name = CFStringCreateWithCString(NULL, angband_sound_name[i],
+                       kTextEncodingUS_ASCII);
+
+               /* Error */
+               if (name == NULL) continue;
+
+               /* Find sound sample resource with the same name */
+               res = get_resource_spec(name, CFSTR("wav"), &spec);
+
+               /* Free the reference to CFString */
+               CFRelease(name);
+
+               /* Error */
+               if (!res) continue;
+
+               /* Open the sound file */
+               err = OpenMovieFile(&spec, &file_id, fsRdPerm);
+
+               /* Error */
+               if (err != noErr) continue;
+
+               /* Create Movie from the file */
+               err = NewMovieFromFile(&movie, file_id, &res_id, movie_name,
+                       newMovieActive, NULL);
+
+               /* Error */
+               if (err != noErr) goto close_file;
+
+               /* Get the first track of the movie */
+               track = GetMovieIndTrackType(movie, 1, AudioMediaCharacteristic,
+                       movieTrackCharacteristic | movieTrackEnabledOnly );
+
+               /* Error */
+               if (track == NULL) goto close_movie;
+
+               /* Allocate a handle to store sample */
+               h = NewHandle(0);
+
+               /* Error */
+               if (h == NULL) goto close_track;
+
+               /* Dump the sample into the handle */
+               err = PutMovieIntoTypedHandle(movie, track, soundListRsrc, h, 0,
+                       GetTrackDuration(track), 0L, NULL);
+
+               /* Success */
+               if (err == noErr)
+               {
+                       /* Store the handle in the sample list */
+                       samples[i] = (SndListHandle)h;
+               }
+
+               /* Failure */
+               else
+               {
+                       /* Free unused handle */
+                       DisposeHandle(h);
+               }
+
+               /* Free the track */
+               close_track: DisposeMovieTrack(track);
+
+               /* Free the movie */
+               close_movie: DisposeMovie(movie);
+
+               /* Close the movie file */
+               close_file: CloseMovieFile(file_id);
+       }
+
+       /* Stop QuickTime */
+       ExitMovies();
+}
+
+#else /* USE_QT_SOUND */
+
+/*
+ * Return a handle of 'snd ' resource given Angband sound event number,
+ * or NULL if it isn't found.
+ *
+ * Globals referenced: angband_sound_name[] (variable.c)
+ */
+static SndListHandle find_sound(int num)
+{
+       Str255 sound;
+
+       /* Get the proper sound name */
+       strnfmt((char*)sound + 1, 255, "%.16s.wav", angband_sound_name[num]);
+       sound[0] = strlen((char*)sound + 1);
+
+       /* Obtain resource XXX XXX XXX */
+       return ((SndListHandle)GetNamedResource('snd ', sound));
+}
+
+#endif /* USE_QT_SOUND */
+
+
+/*
+ * Clean up sound support - to be called when the game exits.
+ *
+ * Globals referenced: channels[], samples[], sample_refs[].
+ */
+static void cleanup_sound(void)
+{
+       int i;
+
+       /* No need to clean it up */
+       if (!channel_initialised) return;
+
+       /* Dispose channels */
+       for (i = 0; i < MAX_CHANNELS; i++)
+       {
+               /* Drain sound commands and free the channel */
+               SndDisposeChannel(channels[i], TRUE);
+       }
+
+       /* Free sound data */
+       for (i = 1; i < SOUND_MAX; i++)
+       {
+               /* Still locked */
+               if ((sample_refs[i] > 0) && (samples[i] != NULL))
+               {
+                       /* Unlock it */
+                       HUnlock((Handle)samples[i]);
+               }
+
+#ifndef USE_QT_SOUND
+
+               /* Release it */
+               if (samples[i]) ReleaseResource((Handle)samples[i]);
+#else
+
+               /* Free handle */
+               if (samples[i]) DisposeHandle((Handle)samples[i]);
+#endif /* !USE_QT_SOUND */
+       }
+}
+
+
+/*
+ * Play sound effects asynchronously -- pelpel
+ *
+ * I don't believe those who first started using the previous implementations
+ * imagined this is *much* more complicated as it may seem.  Anyway, 
+ * introduced round-robin scheduling of channels and made it much more
+ * paranoid about HLock/HUnlock.
+ *
+ * XXX XXX de-refcounting, HUnlock and ReleaseResource should be done
+ * using channel's callback procedures, which set global flags, and
+ * a procedure hooked into CheckEvents does housekeeping.  On the other
+ * hand, this lazy reclaiming strategy keeps things simple (no interrupt
+ * time code) and provides a sort of cache for sound data.
+ *
+ * Globals referenced: channel_initialised, channels[], samples[],
+ *   sample_refs[].
+ * Globals updated: ditto.
+ */
+static void play_sound(int num, SInt16 vol)
+{
+       OSErr err;
+       int i;
+       int prev_num;
+       SndListHandle h;
+       SndChannelPtr chan;
+       SCStatus status;
+
+       static int next_chan;
+       static SInt16 channel_occupants[MAX_CHANNELS];
+       static SndCommand volume_cmd, quiet_cmd;
+
+
+       /* Initialise sound channels */
+       if (!channel_initialised)
+       {
+               for (i = 0; i < MAX_CHANNELS; i++)
+               {
+                       /* Paranoia - Clear occupant table */
+                       /* channel_occupants[i] = 0; */
+
+                       /* Create sound channel for all sounds to play from */
+                       err = SndNewChannel(&channels[i], sampledSynth, initMono, 0L);
+
+                       /* Error */
+                       if (err != noErr)
+                       {
+                               /* Free channels */
+                               while (--i >= 0)
+                               {
+                                       SndDisposeChannel(channels[i], TRUE);
+                               }
+
+                               /* Notify error */
+#ifdef JP
+                               plog("¥µ¥¦¥ó¥É¥Á¥ã¥ó¥Í¥ë¤ò½é´ü²½½ÐÍè¤Þ¤»¤ó!");
+#else
+                               plog("Cannot initialise sound channels!");
+#endif
+
+                               /* Cancel request */
+                               use_sound = arg_sound = FALSE;
+
+                               /* Failure */
+                               return;
+                       }
+               }
+
+               /* First channel to use */
+               next_chan = 0;
+
+               /* Prepare volume command */
+               volume_cmd.cmd = volumeCmd;
+               volume_cmd.param1 = 0;
+               volume_cmd.param2 = 0;
+
+               /* Prepare quiet command */
+               quiet_cmd.cmd = quietCmd;
+               quiet_cmd.param1 = 0;
+               quiet_cmd.param2 = 0;
+
+               /* Initialisation complete */
+               channel_initialised = TRUE;
+       }
+
+       /* Paranoia */
+       if ((num <= 0) || (num >= SOUND_MAX)) return;
+
+       /* Prepare volume command */
+       volume_cmd.param2 = ((SInt32)vol << 16) | vol;
+
+       /* Channel to use (round robin) */
+       chan = channels[next_chan];
+
+       /* See if the resource is already in use */
+       if (sample_refs[num] > 0)
+       {
+               /* Resource in use */
+               h = samples[num];
+
+               /* Increase the refcount */
+               sample_refs[num]++;
+       }
+
+       /* Sound is not currently in use */
+       else
+       {
+               /* Get handle for the sound */
+#ifdef USE_QT_SOUND
+               h = samples[num];
+#else
+               h = find_sound(num);
+#endif /* USE_QT_SOUND */
+
+               /* Sample not available */
+               if (h == NULL) return;
+
+#ifndef USE_QT_SOUND
+
+               /* Load resource */
+               LoadResource((Handle)h);
+
+               /* Remember it */
+               samples[num] = h;
+
+#endif /* !USE_QT_SOUND */
+
+               /* Lock the handle */
+               HLockHi((Handle)h);
+
+               /* Initialise refcount */
+               sample_refs[num] = 1;
+       }
+
+       /* Poll the channel */
+       err = SndChannelStatus(chan, sizeof(SCStatus), &status);
+
+       /* It isn't available */
+       if ((err != noErr) || status.scChannelBusy)
+       {
+               /* Shut it down */
+               SndDoImmediate(chan, &quiet_cmd);
+       }
+
+       /* Previously played sound on this channel */
+       prev_num = channel_occupants[next_chan];
+
+       /* Process previously played sound */
+       if (prev_num != 0)
+       {
+               /* Decrease refcount */
+               sample_refs[prev_num]--;
+
+               /* We can free it now */
+               if (sample_refs[prev_num] <= 0)
+               {
+                       /* Unlock */
+                       HUnlock((Handle)samples[prev_num]);
+
+#ifndef USE_QT_SOUND
+
+                       /* Release */
+                       ReleaseResource((Handle)samples[prev_num]);
+
+                       /* Forget handle */
+                       samples[prev_num] = NULL;
+
+#endif /* !USE_QT_SOUND */
+
+                       /* Paranoia */
+                       sample_refs[prev_num] = 0;
+               }
+       }
+
+       /* Remember this sound as the current occupant of the channel */
+       channel_occupants[next_chan] = num;
+
+       /* Set up volume for channel */
+       SndDoImmediate(chan, &volume_cmd);
+
+       /* Play new sound asynchronously */
+       SndPlay(chan, h, TRUE);
+
+       /* Schedule next channel (round robin) */
+       next_chan++;
+       if (next_chan >= MAX_CHANNELS) next_chan = 0;
+}
+
+# else /* USE_ASYNC_SOUND */
+
+/*
+ * Play sound synchronously
+ *
+ * This may not be your choice, but much safer and much less resource hungry.
+ */
+static void play_sound(int num, SInt16 vol)
+{
+       Handle handle;
+       Str255 sound;
+
+       /* Get the proper sound name */
+       strnfmt((char*)sound + 1, 255, "%.16s.wav", angband_sound_name[num]);
+       sound[0] = strlen((char*)sound + 1);
+
+       /* Obtain resource XXX XXX XXX */
+       handle = GetNamedResource('snd ', sound);
+
+       /* Oops */
+       if (handle == NULL) return;
+
+       /* Load and Lock */
+       LoadResource(handle);
+       HLockHi(handle);
+
+       /* Play sound (wait for completion) */
+       SndPlay(NULL, (SndListHandle)handle, FALSE);
+
+       /* Unlock and release */
+       HUnlock(handle);
+       ReleaseResource(handle);
+}
+
+# endif /* USE_ASYNC_SOUND */
+
+/*
+       Extra Sound Mode
+*/
+
+
+static short soundmode[8];
+
+#define                SND_NON         0
+#define                SND_ATTACK      1
+#define                SND_MOVE                2
+#define                SND_TRAP                3
+#define                SND_SHOP                4
+#define                SND_ME          5
+#define                SND_CMD_ERROR   6
+
+#ifndef MACH_O_CARBON
+
+static int soundchoice[] = {
+       SND_NON,
+       SND_ATTACK,
+       SND_ATTACK,
+       SND_ATTACK,
+       SND_TRAP,
+       SND_ATTACK,
+       SND_ME,
+       SND_ME,
+       SND_ME,
+       SND_MOVE,
+       SND_ATTACK,
+       SND_ME,
+       SND_ATTACK,
+       SND_NON,
+       SND_MOVE,
+       SND_MOVE,
+       SND_ME,
+       SND_SHOP,
+       SND_SHOP,
+       SND_SHOP,
+       SND_SHOP,
+       SND_MOVE,
+       SND_MOVE,
+       SND_MOVE,
+       SND_MOVE,
+       SND_ATTACK,
+       SND_SHOP,
+       SND_SHOP,
+       SND_ME,
+       SND_NON,
+       SND_ATTACK,
+       SND_NON,
+       SND_NON,
+       SND_NON,
+       SND_NON,
+       SND_ATTACK,
+       SND_ATTACK,
+       SND_NON,
+       SND_NON,
+       SND_ATTACK,
+       SND_NON,
+       SND_NON,
+       SND_NON,
+       SND_TRAP,
+       SND_ATTACK,
+       SND_ATTACK,
+       SND_ATTACK,
+       SND_ATTACK,
+       SND_ATTACK,
+       SND_NON,
+       SND_NON,
+       SND_NON,
+       SND_NON,
+       SND_NON,
+       SND_CMD_ERROR,
+       SND_TRAP,
+       SND_NON,
+       SND_NON,
+       SND_TRAP,
+       SND_ATTACK,
+       SND_TRAP,
+       SND_ATTACK,
+       SND_ATTACK,
+       SND_NON,
+       SND_TRAP,
+};
+
+static int ext_sound = 0;
+static int ext_graf = 0;
+
+#endif /* !MACH_O_CARBON */
+
+#endif /* ANGBAND_LITE_MAC */
+
+
+
+/*** Support for the "z-term.c" package ***/
 
 
 /*
@@ -1591,7 +2313,6 @@ static void Term_init_mac(term *t)
 
        /* Block */
        {
-               Rect tempRect;
                Rect globalRect;
                GDHandle mainGDH;
                GDHandle currentGDH;
@@ -1723,48 +2444,77 @@ static errr Term_xtra_mac_react(void)
        }
 
        
-       /* Handle transparency */
-       if (use_newstyle_graphics != arg_newstyle_graphics)
+       /* Handle graphics */
+       if (graf_mode_req != graf_mode)
        {
+               /* dispose old GWorld's if present */
                globe_nuke();
 
-               if (globe_init() != 0)
+               /* Setup parameters according to request */
+               switch (graf_mode_req)
                {
-                       plog("Cannot initialize graphics!");
-                       arg_graphics = FALSE;
-                       arg_newstyle_graphics = FALSE;
-               }
-
-               /* Apply request */
-               use_newstyle_graphics = arg_newstyle_graphics;
+                       /* ASCII - no graphics whatsoever */
+                       case GRAF_MODE_NONE:
+                       {
+                               use_graphics = arg_graphics = GRAPHICS_NONE;
+                               break;
+                       }
 
-               /* Apply and Verify */
-               term_data_check_size(td);
+                       /*
+                        * 8x8 tiles (PICT id 1001)
+                        * no transparency effect
+                        * "old" graphics definitions
+                        */
+                       case GRAF_MODE_8X8:
+                       {
+                               use_graphics = arg_graphics = GRAPHICS_ORIGINAL;
+                               ANGBAND_GRAF = "old";
+#ifdef MACH_O_CARBON
+                               pictID = CFSTR("8x8");
+#else
+                               pictID = 1001;
+#endif /* MACH_O_CARBON */
+                               grafWidth = grafHeight = 8;
+                               break;
+                       }
 
-               /* Resize the window */
-               term_data_resize(td);
-               /* Reset visuals */
-               reset_visuals();
-       }
-       
-       /* Handle graphics */
-       if (use_graphics != arg_graphics)
-       {
-               /* Initialize graphics */
+                       /*
+                        * 16x16 tiles (images: PICT id 1002)
+                        * with transparency effect
+                        * "new" graphics definitions
+                        */
+                       case GRAF_MODE_16X16:
+                       {
+                               use_graphics = arg_graphics = GRAPHICS_ADAM_BOLT;
+                               ANGBAND_GRAF = "new";
+#ifdef MACH_O_CARBON
+                               pictID = CFSTR("16x16");
+#else
+                               pictID = 1002;
+#endif /* MACH_O_CARBON */
+                               grafWidth = grafHeight = 16;
+                               break;
+                       }
+               }
 
-               if (!use_graphics && !frameP && (globe_init() != 0))
+               if ((graf_mode_req != GRAF_MODE_NONE) && !frameP && (globe_init() != 0))
                {
 #ifdef JP
                        plog("¥°¥é¥Õ¥£¥Ã¥¯¤Î½é´ü²½¤Ï½ÐÍè¤Þ¤»¤ó¤Ç¤·¤¿.");
 #else
                        plog("Cannot initialize graphics!");
 #endif
-                       arg_graphics = FALSE;
+
+                       /* reject request */
+                       graf_mode_req = GRAF_MODE_NONE;
+
+                       /* reset graphics flags */
+                       use_graphics = arg_graphics = FALSE;
+
                }
 
-               /* Apply request */
-               use_graphics = arg_graphics;
+               /* update current graphics mode */
+               graf_mode = graf_mode_req;
 
                /* Apply and Verify */
                term_data_check_size(td);
@@ -1814,46 +2564,9 @@ static errr Term_xtra_mac(int n, int v)
                /* Make a sound */
                case TERM_XTRA_SOUND:
                {
-                       Handle handle;
-
-                       Str255 sound;
-
-#if 0
-                       short oldResFile;
-                       short newResFile;
-
-                       /* Open the resource file */
-                       oldResFile = CurResFile();
-                       newResFile = OpenResFile(sound);
-
-                       /* Close the resource file */
-                       CloseResFile(newResFile);
-                       UseResFile(oldResFile);
-#endif
+                       /* Play sound */
+                       play_sound(v, sound_volume);
 
-                       /* Get the proper sound name */
-                       sprintf((char*)sound + 1, "%.16s.wav", angband_sound_name[v]);
-                       sound[0] = strlen((char*)sound + 1);
-
-                       /* Obtain resource XXX XXX XXX */
-                       handle = Get1NamedResource('snd ', sound);
-                       if( handle == NULL || ext_sound )
-                               handle = GetNamedResource('snd ', sound);
-                       
-                       /* Oops */
-                       if (handle && soundmode[soundchoice[v]] == true)
-                       {
-                               /* Load and Lock */
-                               LoadResource(handle);
-                               HLock(handle);
-
-                               /* Play sound (wait for completion) */
-                               SndPlay(nil, (SndListHandle)handle, true);
-
-                               /* Unlock and release */
-                               HUnlock(handle);
-                               ReleaseResource(handle);
-                       }
                        /* Success */
                        return (0);
                }
@@ -1965,7 +2678,7 @@ static errr Term_xtra_mac(int n, int v)
                                 * Even if ticks are 0, it's worth calling for
                                 * the above mentioned reasons.
                                 */
-                               WaitNextEvent(~everyEvent, &tmp, ticks, nil);
+                               WaitNextEvent((EventMask)~everyEvent, &tmp, ticks, nil);
 #else
                                long m = TickCount() + (v * 60L) / 1000;
 
@@ -2101,12 +2814,8 @@ static errr Term_text_mac(int x, int y, int n, byte a, const char *cp)
  *
  * Erase "n" characters starting at (x,y)
  */
-#ifdef USE_TRANSPARENCY
 static errr Term_pict_mac(int x, int y, int n, const byte *ap, const char *cp,
                          const byte *tap, const char *tcp)
-#else
-static errr Term_pict_mac(int x, int y, int n, const byte *ap, const char *cp)
-#endif
 {
        int i;
        Rect r2;
@@ -2114,8 +2823,6 @@ static errr Term_pict_mac(int x, int y, int n, const byte *ap, const char *cp)
        GDHandle saveGDevice;
        GWorldPtr saveGWorld;
        
-       PixMapHandle PortPix;
-       
        /* Save GWorld */
        GetGWorld(&saveGWorld, &saveGDevice);
        
@@ -2184,7 +2891,6 @@ static errr Term_pict_mac(int x, int y, int n, const byte *ap, const char *cp)
                        int col, row;
                        Rect r1;
 
-#ifdef USE_TRANSPARENCY
                        Rect terrain_r;
                        bool terrain_flag = FALSE;
                        byte ta = tap[i];
@@ -2205,7 +2911,6 @@ static errr Term_pict_mac(int x, int y, int n, const byte *ap, const char *cp)
 
                                terrain_flag = TRUE;
                        }
-#endif
 
                        /* Row and Col */
                        row = ((byte)a & 0x7F);
@@ -2229,7 +2934,6 @@ static errr Term_pict_mac(int x, int y, int n, const byte *ap, const char *cp)
 #endif
                        if (use_bigtile) r2.right += td->tile_wid;
 
-#ifdef USE_TRANSPARENCY
                        if (terrain_flag)
                        {
                                /*
@@ -2261,7 +2965,6 @@ static errr Term_pict_mac(int x, int y, int n, const byte *ap, const char *cp)
 #endif
                        }
                        else
-#endif /* USE_TRANSPARENCY */
                        {
 #if TARGET_API_MAC_CARBON
                                CopyBits( (BitMap *) *srcBitMap, (BitMap *) *destBitMap, &r1, &r2, srcCopy, NULL);
@@ -2390,6 +3093,74 @@ static void term_data_link(int i)
 
 
 
+#ifdef MACH_O_CARBON
+
+/*
+ * (Carbon, Bundle)
+ * Return a POSIX pathname of the lib directory, or NULL if it can't be
+ * located.  Caller must supply a buffer along with its size in bytes,
+ * where returned pathname will be stored.
+ * I prefer use of goto's to several nested if's, if they involve error
+ * handling.  Sorry if you are offended by their presence.  Modern
+ * languages have neater constructs for this kind of jobs -- pelpel
+ */
+static char *locate_lib(char *buf, size_t size)
+{
+       CFURLRef main_url = NULL;
+       CFStringRef main_str = NULL;
+       char *p;
+       char *res = NULL;
+
+       /* Obtain the URL of the main bundle */
+       main_url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
+
+       /* Oops */
+       if (main_url == NULL) goto ret;
+
+       /* Convert it to POSIX pathname */
+       main_str = CFURLCopyFileSystemPath(main_url, kCFURLPOSIXPathStyle);
+
+       /* Oops */
+       if (main_str == NULL) goto ret;
+
+       /* Convert it again from darn unisomething encoding to ASCII */
+       if (CFStringGetCString(main_str, buf, size, kTextEncodingUS_ASCII) == FALSE)
+               goto ret;
+
+       /* Find the last '/' in the pathname */
+       p = strrchr(buf, '/');
+
+       /* Paranoia - cannot happen */
+       if (p == NULL) goto ret;
+
+       /* Remove the trailing path */
+       *p = '\0';
+
+       /*
+        * Paranoia - bounds check, with 5 being the length of "/lib/"
+        * and 1 for terminating '\0'.
+        */
+       if (strlen(buf) + 5 + 1 > size) goto ret;
+
+       /* Append "/lib/" */
+       strcat(buf, "/lib/");
+
+       /* Set result */
+       res = buf;
+
+ret:
+
+       /* Release objects allocated and implicitly retained by the program */
+       if (main_str) CFRelease(main_str);
+       if (main_url) CFRelease(main_url);
+
+       /* pathname of the lib folder or NULL */
+       return (res);
+}
+
+
+#else /* MACH_O_CARBON */
+
 
 /*
  * Set the "current working directory" (also known as the "default"
@@ -2441,9 +3212,250 @@ static void SetupAppDir(void)
        }
 }
 
+#endif
+
+
+
+#if TARGET_API_MAC_CARBON
+/*
+ * Using Core Foundation's Preferences services -- pelpel
+ *
+ * Requires OS 8.6 or greater with CarbonLib 1.1 or greater. Or OS X,
+ * of course.
+ *
+ * Without this, we can support older versions of OS 8 as well
+ * (with CarbonLib 1.0.4).
+ *
+ * Frequent allocation/deallocation of small chunks of data is
+ * far from my liking, but since this is only called at the
+ * beginning and the end of a session, I hope this hardly matters.
+ */
+
+
+/*
+ * Store "value" as the value for preferences item name
+ * pointed by key
+ */
+static void save_pref_short(const char *key, short value)
+{
+       CFStringRef cf_key;
+       CFNumberRef cf_value;
+
+       /* allocate and initialise the key */
+       cf_key = CFStringCreateWithCString(NULL, key, kTextEncodingUS_ASCII);
+
+       /* allocate and initialise the value */
+       cf_value = CFNumberCreate(NULL, kCFNumberShortType, &value);
+
+       if ((cf_key != NULL) && (cf_value != NULL))
+       {
+               /* Store the key-value pair in the applications preferences */
+               CFPreferencesSetAppValue(
+                       cf_key,
+                       cf_value,
+                       kCFPreferencesCurrentApplication);
+       }
+
+       /*
+        * Free CF data - the reverse order is a vain attempt to
+        * minimise memory fragmentation.
+        */
+       if (cf_value) CFRelease(cf_value);
+       if (cf_key) CFRelease(cf_key);
+}
+
+
+/*
+ * Load preference value for key, returns TRUE if it succeeds with
+ * vptr updated appropriately, FALSE otherwise.
+ */
+static bool query_load_pref_short(const char *key, short *vptr)
+{
+       CFStringRef cf_key;
+       CFNumberRef cf_value;
+
+       /* allocate and initialise the key */
+       cf_key = CFStringCreateWithCString(NULL, key, kTextEncodingUS_ASCII);
+
+       /* Oops */
+       if (cf_key == NULL) return (FALSE);
+
+       /* Retrieve value for the key */
+       cf_value = CFPreferencesCopyAppValue(
+               cf_key,
+               kCFPreferencesCurrentApplication);
+
+       /* Value not found */
+       if (cf_value == NULL)
+       {
+               CFRelease(cf_key);
+               return (FALSE);
+       }
+
+       /* Convert the value to short */
+       CFNumberGetValue(
+               cf_value,
+               kCFNumberShortType,
+               vptr);
+
+       /* Free CF data */
+       CFRelease(cf_value);
+       CFRelease(cf_key);
+
+       /* Success */
+       return (TRUE);
+}
+
+
+/*
+ * Update short data pointed by vptr only if preferences
+ * value for key is located.
+ */
+static void load_pref_short(const char *key, short *vptr)
+{
+       short tmp;
+
+       if (query_load_pref_short(key, &tmp)) *vptr = tmp;
+       return;
+}
+
+
+/*
+ * Save preferences to preferences file for current host+current user+
+ * current application.
+ */
+static void cf_save_prefs()
+{
+       int i;
+
+       /* Version stamp */
+       save_pref_short("version.major", FAKE_VERSION);
+       save_pref_short("version.minor", FAKE_VER_MAJOR);
+       save_pref_short("version.patch", FAKE_VER_MINOR);
+       save_pref_short("version.extra", FAKE_VER_PATCH);
+
+       /* Gfx settings */
+       save_pref_short("arg.arg_sound", arg_sound);
+       save_pref_short("arg.graf_mode", graf_mode);
+       save_pref_short("arg.arg_bigtile", arg_bigtile);
+
+#ifndef MACH_O_CARBON
+       /* SoundMode */
+       for( i = 0 ; i < 7 ; i++ )
+               save_pref_short(format("sound%d.on", i), soundmode[i]);
+#endif /* MACH_O_CARBON */
+
+       /* Windows */
+       for (i = 0; i < MAX_TERM_DATA; i++)
+       {
+               term_data *td = &data[i];
+
+               save_pref_short(format("term%d.mapped", i), td->mapped);
+
+               save_pref_short(format("term%d.font_id", i), td->font_id);
+               save_pref_short(format("term%d.font_size", i), td->font_size);
+               save_pref_short(format("term%d.font_face", i), td->font_face);
+
+               save_pref_short(format("term%d.tile_wid", i), td->tile_wid);
+               save_pref_short(format("term%d.tile_hgt", i), td->tile_hgt);
+
+               save_pref_short(format("term%d.cols", i), td->cols);
+               save_pref_short(format("term%d.rows", i), td->rows);
+               save_pref_short(format("term%d.left", i), td->r.left);
+               save_pref_short(format("term%d.top", i), td->r.top);
+       }
+
+       /*
+        * Make sure preferences are persistent
+        */
+       CFPreferencesAppSynchronize(
+               kCFPreferencesCurrentApplication);
+}
+
+
+/*
+ * Load preferences from preferences file for current host+current user+
+ * current application.
+ */
+static void cf_load_prefs()
+{
+       bool ok;
+       short pref_major, pref_minor, pref_patch, pref_extra;
+       int i;
+
+       /* Assume nothing is wrong, yet */
+       ok = TRUE;
+
+       /* Load version information */
+       ok &= query_load_pref_short("version.major", &pref_major);
+       ok &= query_load_pref_short("version.minor", &pref_minor);
+       ok &= query_load_pref_short("version.patch", &pref_patch);
+       ok &= query_load_pref_short("version.extra", &pref_extra);
+
+       /* Any of the above failed */
+       if (!ok)
+       {
+               /* This may be the first run */
+#ifdef JP
+               mac_warning("½é´üÀßÄê¥Õ¥¡¥¤¥ë¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó¡£");
+#else
+               mac_warning("Preferences are not found.");
+#endif
+
+               /* Ignore the rest */
+               return;
+       }
+
+       /* Gfx settings */
+       {
+               short pref_tmp;
+
+               /* sound */
+               if (query_load_pref_short("arg.arg_sound", &pref_tmp))
+                       arg_sound = pref_tmp;
+
+               /* graphics */
+               if (query_load_pref_short("arg.graf_mode", &pref_tmp))
+                       graf_mode_req = pref_tmp;
+
+               /* double-width tiles */
+               if (query_load_pref_short("arg.arg_bigtile", &pref_tmp))
+               {
+                       arg_bigtile = use_bigtile = pref_tmp;
+               }
+
+       }
+
+#ifndef MACH_O_CARBON
+       /* SoundMode */
+       for( i = 0 ; i < 7 ; i++ )
+       {
+               query_load_pref_short(format("sound%d.on", i), &soundmode[i]);
+       }
+#endif /* MACH_O_CARBON */
+
+       /* Windows */
+       for (i = 0; i < MAX_TERM_DATA; i++)
+       {
+               term_data *td = &data[i];
+
+               load_pref_short(format("term%d.mapped", i), &td->mapped);
+
+               load_pref_short(format("term%d.font_id", i), &td->font_id);
+               load_pref_short(format("term%d.font_size", i), &td->font_size);
+               load_pref_short(format("term%d.font_face", i), &td->font_face);
 
+               load_pref_short(format("term%d.tile_wid", i), &td->tile_wid);
+               load_pref_short(format("term%d.tile_hgt", i), &td->tile_hgt);
 
+               load_pref_short(format("term%d.cols", i), &td->cols);
+               load_pref_short(format("term%d.rows", i), &td->rows);
+               load_pref_short(format("term%d.left", i), &td->r.left);
+               load_pref_short(format("term%d.top", i), &td->r.top);
+       }
+}
 
+#else
 /*
  * Global "preference" file pointer
  */
@@ -2488,8 +3500,7 @@ static void save_prefs(void)
        putshort(FAKE_VER_PATCH);
 
        putshort(arg_sound);
-       putshort(arg_graphics);
-       putshort(arg_newstyle_graphics);
+       putshort(graf_mode);
        putshort(arg_bigtile);
        
        /* SoundMode */
@@ -2560,25 +3571,7 @@ static void load_prefs(void)
        }
 
        arg_sound = getshort();
-       arg_graphics = getshort();
-       arg_newstyle_graphics = getshort();
-       use_newstyle_graphics = arg_newstyle_graphics;
-       
-       if (use_newstyle_graphics == true)
-       {
-               ANGBAND_GRAF = "new";
-               arg_newstyle_graphics = true;
-               grafWidth = grafHeight = 16;
-               pictID = 1002;
-       }
-       else
-       {
-               ANGBAND_GRAF = "old";
-               arg_newstyle_graphics = false;
-               grafWidth = grafHeight = 8;
-               pictID = 1001;
-       }
-
+       graf_mode_req = getshort();
        arg_bigtile = getshort();
        use_bigtile = arg_bigtile;
        
@@ -2586,29 +3579,6 @@ static void load_prefs(void)
        for( i = 0 ; i < 7 ; i++ )
                soundmode[i] = getshort();
        
-       /* Special menu */
-       m = GetMenuHandle(134);
-
-#if TARGET_API_MAC_CARBON
-       /* Item "arg_sound" */
-       CheckMenuItem(m, 1, arg_sound);
-
-       /* Item "arg_graphics" */
-       CheckMenuItem(m, 2, arg_graphics);
-       
-       /* Item "arg_newstyle_graphics"*/
-       CheckMenuItem(m, 8, arg_newstyle_graphics);
-#else
-       /* Item "arg_sound" */
-       CheckItem(m, 1, arg_sound);
-
-       /* Item "arg_graphics" */
-       CheckItem(m, 2, arg_graphics);
-       
-       /* Item "arg_newstyle_graphics"*/
-       CheckItem(m, 8, arg_newstyle_graphics);
-#endif
-
        /* Windows */
        for (i = 0; i < MAX_TERM_DATA; i++)
        {
@@ -2634,7 +3604,7 @@ static void load_prefs(void)
                if (feof(fff)) break;
        }
 }
-
+#endif /* TARGET_API_MAC_CARBON */
 
 
 
@@ -2645,18 +3615,24 @@ static void term_data_hack(term_data *td)
 {
        short fid;
 
-#ifdef JP
 #if TARGET_API_MAC_CARBON
+#ifdef JP
        /* Default to Osaka font (Japanese) */
        fid = FMGetFontFamilyFromName( "\pOsaka¡ÝÅùÉý" );
 #else
+       /* Default to Monaco font */
+       fid = FMGetFontFamilyFromName("\pmonaco");
+#endif
+#else
+#ifdef JP
+       /* Default to ÅùÉýÌÀÄ« font (Japanese) */
        GetFNum( "\pÅùÉýÌÀÄ«", &fid);
        SetFScaleDisable( true );
-#endif
 #else
        /* Default to Monaco font */
        GetFNum("\pmonaco", &fid);
 #endif
+#endif
 
        /* Wipe it */
        WIPE(td, term_data);
@@ -2707,12 +3683,16 @@ static void init_windows(void)
 
        term_data *td;
 
+#if !TARGET_API_MAC_CARBON
+
        SysEnvRec env;
        short savev;
        long saved;
 
        bool oops;
 
+#endif /* !TARGET_API_MAC_CARBON */
+
 
        /*** Default values ***/
 
@@ -2754,7 +3734,10 @@ static void init_windows(void)
 
 
        /*** Load preferences ***/
-
+       
+#if TARGET_API_MAC_CARBON
+       cf_load_prefs();
+#else
        /* Assume failure */
        oops = TRUE;
 
@@ -2797,8 +3780,6 @@ static void init_windows(void)
 
 #endif /* USE_SFL_CODE */
 
-#if TARGET_API_MAC_CARBON
-#else
        /* Oops */
        if (oops)
        {
@@ -2815,7 +3796,6 @@ static void init_windows(void)
                /* Restore */
                HSetVol(0, savev, saved);
        }
-#endif
 
        /* Load preferences */
        if (fff)
@@ -2826,6 +3806,7 @@ static void init_windows(void)
                /* Close the file */
                my_fclose(fff);
        }
+#endif /* TARGET_API_MAC_CARBON */
 
 
        /*** Instantiate ***/
@@ -2852,6 +3833,8 @@ static void init_windows(void)
        Term_activate(td->t);
 }
 
+#ifndef MACH_O_CARBON
+
 static void init_sound( void )
 {
        int err, i;
@@ -2992,6 +3975,8 @@ static void init_graf( void )
        }
 }
 
+#endif /* MACH_O_CARBON */
+
 #ifdef CHUUKEI
 /*
 
@@ -3094,7 +4079,6 @@ short GetCheck( DialogPtr targetDlg, short check )
 void SoundConfigDLog(void)
 {
        DialogPtr dialog;
-       Rect r;
        short item_hit;
        int     i;
 
@@ -3127,6 +4111,12 @@ void SoundConfigDLog(void)
 /*
  * Exit the program
  */
+#if TARGET_API_MAC_CARBON
+static void save_pref_file(void)
+{
+       cf_save_prefs();
+}
+#else
 static void save_pref_file(void)
 {
        bool oops;
@@ -3183,8 +4173,6 @@ static void save_pref_file(void)
 
 #endif /* USE_SFL_CODE */
 
-#if TARGET_API_MAC_CARBON
-#else
        /* Oops */
        if (oops)
        {
@@ -3202,7 +4190,6 @@ static void save_pref_file(void)
                /* Restore */
                HSetVol(0, savev, saved);
        }
-#endif
 
        /* Save preferences */
        if (fff)
@@ -3214,8 +4201,11 @@ static void save_pref_file(void)
                my_fclose(fff);
        }
 }
+#endif
+
 
 
+#if defined(__MWERKS__)
 
 /*
  * A simple "Yes/No" filter to parse "key press" events in dialog windows
@@ -3262,6 +4252,139 @@ static pascal Boolean ynfilter(DialogPtr dialog, EventRecord *event, short *ip)
        return (0);
 }
 
+#endif /* __MWERKS__ */
+
+
+#if TARGET_API_MAC_CARBON
+
+/*
+ * Prepare savefile dialogue and set the variable
+ * savefile accordingly. Returns true if it succeeds, false (or
+ * aborts) otherwise. If all is false, only allow files whose type
+ * is 'SAVE'.
+ * Originally written by Peter Ammon
+ */
+static bool select_savefile(bool all)
+{
+       OSErr err;
+       FSSpec theFolderSpec;
+       FSSpec savedGameSpec;
+       NavDialogOptions dialogOptions;
+       NavReplyRecord reply;
+       /* Used only when 'all' is true */
+       NavTypeList types = {ANGBAND_CREATOR, 1, 1, {'SAVE'}};
+       NavTypeListHandle myTypeList;
+       AEDesc defaultLocation;
+
+#ifdef MACH_O_CARBON
+
+       /* Find the save folder */
+       err = path_to_spec(ANGBAND_DIR_SAVE, &theFolderSpec);
+
+#else
+
+       /* Find :lib:save: folder */
+       err = FSMakeFSSpec(app_vol, app_dir, "\p:lib:save:", &theFolderSpec);
+
+#endif
+
+       /* Oops */
+       if (err != noErr) quit("Unable to find the folder :lib:save:");
+
+       /* Get default Navigator dialog options */
+       err = NavGetDefaultDialogOptions(&dialogOptions);
+
+       /* Clear preview option */
+       dialogOptions.dialogOptionFlags &= ~kNavAllowPreviews;
+
+       /* Disable multiple file selection */
+       dialogOptions.dialogOptionFlags &= ~kNavAllowMultipleFiles;
+
+       /* Make descriptor for default location */
+       err = AECreateDesc(typeFSS, &theFolderSpec, sizeof(FSSpec),
+               &defaultLocation);
+
+       /* Oops */
+       if (err != noErr) quit("Unable to allocate descriptor");
+
+       /* We are indifferent to signature and file types */
+       if (all)
+       {
+               myTypeList = (NavTypeListHandle)nil;
+       }
+
+       /* Set up type handle */
+       else
+       {
+               err = PtrToHand(&types, (Handle *)&myTypeList, sizeof(NavTypeList));
+
+               /* Oops */
+               if (err != noErr) quit("Error in PtrToHand. Try enlarging heap");
+
+       }
+
+       /* Call NavGetFile() with the types list */
+       err = NavChooseFile(&defaultLocation, &reply, &dialogOptions, NULL,
+               NULL, NULL, myTypeList, NULL);
+
+       /* Free type list */
+       if (!all) DisposeHandle((Handle)myTypeList);
+
+       /* Error */
+       if (err != noErr)
+       {
+               /* Nothing */
+       }
+
+       /* Invalid response -- allow the user to cancel */
+       else if (!reply.validRecord)
+       {
+               /* Hack -- Fake error */
+               err = -1;
+       }
+
+       /* Retrieve FSSpec from the reply */
+       else
+       {
+               AEKeyword theKeyword;
+               DescType actualType;
+               Size actualSize;
+
+               /* Get a pointer to selected file */
+               (void)AEGetNthPtr(&reply.selection, 1, typeFSS, &theKeyword,
+                       &actualType, &savedGameSpec, sizeof(FSSpec), &actualSize);
+
+               /* Dispose NavReplyRecord, resources and descriptors */
+               (void)NavDisposeReply(&reply);
+       }
+
+       /* Dispose location info */
+       AEDisposeDesc(&defaultLocation);
+
+       /* Error */
+       if (err != noErr) return (FALSE);
+
+#ifdef MACH_O_CARBON
+
+       /* Convert FSSpec to pathname and store it in variable savefile */
+       (void)spec_to_path(&savedGameSpec, savefile, sizeof(savefile));
+
+#else
+
+       /* Convert FSSpec to pathname and store it in variable savefile */
+       refnum_to_name(
+               savefile,
+               savedGameSpec.parID,
+               savedGameSpec.vRefNum,
+               (char *)savedGameSpec.name);
+
+#endif
+
+       /* Success */
+       return (TRUE);
+}
+#endif
+
 
 /*
  * Handle menu: "File" + "New"
@@ -3291,37 +4414,14 @@ static void do_menu_file_new(void)
 #if TARGET_API_MAC_CARBON
 static void do_menu_file_open(bool all)
 {
-       int err;
-       short vrefnum;
-       long drefnum;
-       long junk;
-       DirInfo pb;
-       SFTypeList types;
-       SFReply reply;
-       Point topleft;
-       BitMap screen;
-       FSSpec  fsp;
-       char path[1024];
-       
-       refnum_to_name(path, app_dir, app_vol, (char*)("\plib:save:"));
-       
-       FSpLocationFromFullPath( strlen(path), path, &fsp );
-       
-       /* Get any file */
-       ChooseFile( (StringPtr)savefile, fsp );
-       
-       /* Allow cancel */
-       if (err != noErr) return;
+       /* Let the player to choose savefile */
+       if (!select_savefile(all)) return;
 
-       /* Extract textual file name for save file */
-/*     GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
-       refnum_to_name(savefile, drefnum, vrefnum, (char*)reply.fName);
-*/
        /* Hack */
        HiliteMenu(0);
 
        /* Game is in progress */
-       game_in_progress = 1;
+       game_in_progress = TRUE;
 
        /* Flush input */
        flush();
@@ -3463,11 +4563,6 @@ static void handle_open_when_ready(void)
 /*
  * Initialize the menus
  *
- * Verify menus 128, 129, 130
- * Create menus 131, 132, 133, 134
- *
- * The standard menus are:
- *
  *   Apple (128) =   { About, -, ... }
  *   File (129) =    { New,Open,Import,Close,Save,-,Exit,Quit }
  *   Edit (130) =    { Cut, Copy, Paste, Clear }   (?)
@@ -3475,9 +4570,70 @@ static void handle_open_when_ready(void)
  *   Size (132) =    { ... }
  *   Window (133) =  { Angband, Mirror, Recall, Choice,
  *                     Term-4, Term-5, Term-6, Term-7 }
- *   Special (134) = { arg_sound, arg_graphics, -,
- *                     arg_fiddle, arg_wizard }
+ *   Special (134) = { Sound, Graphics, TileWidth, TileHeight, -,
+ *                     Fiddle, Wizard }
  */
+
+/* Apple menu */
+#define MENU_APPLE     128
+#define ITEM_ABOUT     1
+
+/* File menu */
+#define MENU_FILE      129
+# define ITEM_NEW      1
+# define ITEM_OPEN     2
+# define ITEM_IMPORT   3
+# define ITEM_CLOSE    4
+# define ITEM_SAVE     5
+#  define ITEM_QUIT    7
+
+/* Edit menu */
+#define MENU_EDIT      130
+# define ITEM_UNDO     1
+# define ITEM_CUT      3
+# define ITEM_COPY     4
+# define ITEM_PASTE    5
+# define ITEM_CLEAR    6
+
+/* Font menu */
+#define MENU_FONT      131
+# define ITEM_BOLD     1
+# define ITEM_WIDE     2
+
+/* Size menu */
+#define MENU_SIZE      132
+
+/* Windows menu */
+#define MENU_WINDOWS   133
+
+/* Special menu */
+#define MENU_SPECIAL   134
+# define ITEM_SOUND    1
+# define ITEM_GRAPH    2
+# define ITEM_TILEWIDTH 3
+# define ITEM_TILEHEIGHT 4
+# define ITEM_FIDDLE   6
+# define ITEM_WIZARD   7
+
+/* Sounds submenu */
+#define SUBMENU_SOUND  143
+# define ITEM_USE_SOUND        1
+# define ITEM_SOUND_SETTING    2
+
+/* Graphics submenu */
+#define SUBMENU_GRAPH  144
+# define ITEM_NONE     1
+# define ITEM_8X8      2
+# define ITEM_16X16    3
+# define ITEM_BIGTILE 5        
+
+/* TileWidth submenu */
+#define SUBMENU_TILEWIDTH      145
+
+/* TileHeight submenu */
+#define SUBMENU_TILEHEIGHT     146
+
+
 static void init_menubar(void)
 {
        int i, n;
@@ -3487,62 +4643,55 @@ static void init_menubar(void)
        WindowPtr tmpw;
 
        MenuHandle m;
-       OSErr           err;
-       long            response;
+
+       Handle mbar;
+
+#if TARGET_API_MAC_CARBON
+       OSErr err;
+       long response;
+#endif
 
        /* Get the "apple" menu */
-       m = GetMenu(128);
+       mbar = GetNewMBar(128);
 
-       /* Insert the menu */
-       InsertMenu(m, 0);
+       /* Whoops! */
+#ifdef JP
+       if (mbar == nil) quit("¥á¥Ë¥å¡¼¥Ð¡¼ ID 128¤ò¸«¤Ä¤±¤ë»ö¤¬¤Ç¤­¤Þ¤»¤ó!");
+#else
+       if (mbar == nil) quit("Cannot find menubar('MBAR') id 128!");
+#endif
+
+       /* Insert them into the current menu list */
+       SetMenuBar(mbar);
+
+       /* Free handle */
+       DisposeHandle(mbar);
+
+#if !TARGET_API_MAC_CARBON
+       /* Apple menu (id 128) */
+       m = GetMenuHandle(MENU_APPLE);
 
        /* Add the DA's to the "apple" menu */
-#if TARGET_API_MAC_CARBON
-#else
        AppendResMenu   (m, 'DRVR');
 #endif
 
        /* Get the "File" menu */
 #if TARGET_API_MAC_CARBON
-       m = GetMenu(129);
+       m = GetMenu(MENU_FILE);
        err = Gestalt( gestaltSystemVersion, &response );
        if ( (err == noErr) && (response >= 0x00000A00) )
        {
-               DeleteMenuItem( m, 7 );
+               DeleteMenuItem(m, ITEM_QUIT);
        }
-#else
-       m = GetMenu(129);
 #endif
 
-       /* Insert the menu */
-       InsertMenu(m, 0);
-
-
-       /* Get the "Edit" menu */
-       m = GetMenu(130);
-
-       /* Insert the menu */
-       InsertMenu(m, 0);
-
-
-       /* Make the "Font" menu */
-       #ifdef JP
-       m = NewMenu(131, "\p¥Õ¥©¥ó¥È");
-       #else
-       m = NewMenu(131, "\pFont");
-       #endif
-       
-       /* Insert the menu */
-       InsertMenu(m, 0);
-
-       /* Add "bold" */
-       AppendMenu(m, "\pBold");
+       /* Edit menu (id 130) - we don't have to do anything */
 
-       /* Add "wide" */
-       AppendMenu(m, "\pWide");
-
-       /* Add a separator */
-       AppendMenu(m, "\p-");
+       /*
+        * Font menu (id 131) - append names of mono-spaced fonts
+        * followed by all available ones
+        */
+       m = GetMenuHandle(MENU_FONT);
 
        /* Fake window */
        r.left = r.right = r.top = r.bottom = 0;
@@ -3610,15 +4759,8 @@ static void init_menubar(void)
        AppendResMenu   (m, 'FONT');
 
 
-       /* Make the "Size" menu */
-       #ifdef JP
-       m = NewMenu(132, "\p¥µ¥¤¥º");
-       #else
-       m = NewMenu(132, "\pSize");
-       #endif
-       
-       /* Insert the menu */
-       InsertMenu(m, 0);
+       /* Size menu (id 132) */
+       m = GetMenuHandle(MENU_SIZE);
 
        /* Add some sizes (stagger choices) */
        for (i = 8; i <= 32; i += ((i / 16) + 1))
@@ -3634,15 +4776,8 @@ static void init_menubar(void)
        }
 
 
-       /* Make the "Windows" menu */
-       #ifdef JP
-       m = NewMenu(133, "\p¥¦¥¤¥ó¥É¥¦");
-       #else
-       m = NewMenu(133, "\pWindows");
-       #endif
-       
-       /* Insert the menu */
-       InsertMenu(m, 0);
+       /* Windows menu (id 133) */
+       m = GetMenuHandle(MENU_WINDOWS);
 
        /* Default choices */
        for (i = 0; i < MAX_TERM_DATA; i++)
@@ -3661,48 +4796,104 @@ static void init_menubar(void)
        }
 
 
-       /* Make the "Special" menu */
-       #ifdef JP
-       m = NewMenu(134, "\pÆÃÊÌ");
-       #else
-       m = NewMenu(134, "\pSpecial");
-       #endif
-       
-       /* Insert the menu */
-       InsertMenu(m, 0);
+#if TARGET_API_MAC_CARBON && !defined(MAC_MPW)
 
-       /* Append the choices */
-       #ifdef JP
-       AppendMenu(m, "\p¥µ¥¦¥ó¥É»ÈÍÑ");
-       AppendMenu(m, "\p¥°¥é¥Õ¥£¥Ã¥¯»ÈÍÑ");
-       AppendMenu(m, "\p-");
-       AppendMenu(m, "\parg_fiddle");
-       AppendMenu(m, "\parg_wizard");
-       AppendMenu(m, "\p-");
-       AppendMenu(m, "\p¥µ¥¦¥ó¥ÉÀßÄê...");
-       AppendMenu(m, "\p16X16¥°¥é¥Õ¥£¥Ã¥¯");
-       AppendMenu(m, "\p£²ÇÜÉý¥¿¥¤¥ëɽ¼¨");
-       #else
-       AppendMenu(m, "\parg_sound");
-       AppendMenu(m, "\parg_graphics");
-       AppendMenu(m, "\p-");
-       AppendMenu(m, "\parg_fiddle");
-       AppendMenu(m, "\parg_wizard");
-       AppendMenu(m, "\p-");
-       AppendMenu(m, "\pSound config");
-       AppendMenu(m, "\pAdam Bolt tile");
-       AppendMenu(m, "\pBigtile Mode");
-       #endif
+       /* CW or gcc -- Use recommended interface for hierarchical menus */
 
-       /* Make the "TileWidth" menu */
-       #ifdef JP
-       m = NewMenu(135, "\p¥¿¥¤¥ëÉý");
-       #else
-       m = NewMenu(135, "\pTileWidth");
-       #endif
+       /* Special menu (id 134) */
+       m = GetMenuHandle(MENU_SPECIAL);
 
-       /* Insert the menu */
-       InsertMenu(m, 0);
+       /* Insert Graphics submenu (id 143) */
+       {
+               MenuHandle submenu;
+
+               /* Get the submenu */
+               submenu = GetMenu(SUBMENU_SOUND);
+
+               /* Insert it */
+               SetMenuItemHierarchicalMenu(m, ITEM_SOUND, submenu);
+       }
+
+       /* Insert Graphics submenu (id 144) */
+       {
+               MenuHandle submenu;
+
+               /* Get the submenu */
+               submenu = GetMenu(SUBMENU_GRAPH);
+
+               /* Insert it */
+               SetMenuItemHierarchicalMenu(m, ITEM_GRAPH, submenu);
+       }
+
+       /* Insert TileWidth submenu (id 145) */
+       {
+               MenuHandle submenu;
+
+               /* Get the submenu */
+               submenu = GetMenu(SUBMENU_TILEWIDTH);
+
+               /* Add some sizes */
+               for (i = 4, n = 1; i <= 32; i++, n++)
+               {
+                       Str15 buf;
+
+                       /* Textual size */
+                       strnfmt((char*)buf + 1, 15, "%d", i);
+                       buf[0] = strlen((char*)buf + 1);
+
+                       /* Append item */
+                       AppendMenu(submenu, buf);
+               }
+
+               /* Insert it */
+               SetMenuItemHierarchicalMenu(m, ITEM_TILEWIDTH, submenu);
+       }
+
+       /* Insert TileHeight submenu (id 146) */
+       {
+               MenuHandle submenu;
+
+               /* Get the submenu */
+               submenu = GetMenu(SUBMENU_TILEHEIGHT);
+
+
+               /* Add some sizes */
+               for (i = 4, n = 1; i <= 32; i++, n++)
+               {
+                       Str15 buf;
+
+                       /* Textual size */
+                       strnfmt((char*)buf + 1, 15, "%d", i);
+                       buf[0] = strlen((char*)buf + 1);
+
+                       /* Append item */
+                       AppendMenu(submenu, buf);
+               }
+
+               /* Insert it */
+               SetMenuItemHierarchicalMenu(m, ITEM_TILEHEIGHT, submenu);
+       }
+
+#else
+
+       /* Special menu (id 134) */
+
+       /* Get graphics (sub)menu (id 143) */
+       m = GetMenu(SUBMENU_SOUND);
+
+       /* Insert it as a submenu */            
+       InsertMenu(m, hierMenu);
+
+
+       /* Get graphics (sub)menu (id 144) */
+       m = GetMenu(SUBMENU_GRAPH);
+
+       /* Insert it as a submenu */            
+       InsertMenu(m, hierMenu);
+
+
+       /* Get TileWidth (sub)menu (id 145) */
+       m = GetMenu(SUBMENU_TILEWIDTH);
 
        /* Add some sizes */
        for (i = 4; i <= 32; i++)
@@ -3718,15 +4909,11 @@ static void init_menubar(void)
        }
 
 
-       /* Make the "TileHeight" menu */
-       #ifdef JP
-       m = NewMenu(136, "\p¥¿¥¤¥ë¹â");
-       #else
-       m = NewMenu(136, "\pTileHeight");
-       #endif
+       /* Insert it as a submenu */
+       InsertMenu(m, hierMenu);
 
-       /* Insert the menu */
-       InsertMenu(m, 255);
+       /* Get TileHeight (sub)menu (id 146) */
+       m = GetMenu(SUBMENU_TILEHEIGHT);
 
        /* Add some sizes */
        for (i = 4; i <= 32; i++)
@@ -3742,6 +4929,10 @@ static void init_menubar(void)
        }
 
 
+       /* Insert the menu */
+       InsertMenu(m, hierMenu);
+
+#endif
        /* Update the menu bar */
        DrawMenuBar();
 }
@@ -3775,7 +4966,7 @@ static void setup_menus(void)
 
 
        /* File menu */
-       m = GetMenuHandle(129);
+       m = GetMenuHandle(MENU_FILE);
 
        /* Get menu size */
 #if TARGET_API_MAC_CARBON
@@ -3801,13 +4992,13 @@ static void setup_menus(void)
        if (initialized && !game_in_progress)
        {
 #if TARGET_API_MAC_CARBON
-               EnableMenuItem(m, 1);
-               EnableMenuItem(m, 2);
-               EnableMenuItem(m, 3);
+               EnableMenuItem(m, ITEM_NEW);
+               EnableMenuItem(m, ITEM_OPEN);
+               EnableMenuItem(m, ITEM_IMPORT);
 #else
-               EnableItem(m, 1);
-               EnableItem(m, 2);
-               EnableItem(m, 3);
+               EnableItem(m, ITEM_NEW);
+               EnableItem(m, ITEM_OPEN);
+               EnableItem(m, ITEM_IMPORT);
 #endif
        }
 
@@ -3815,9 +5006,9 @@ static void setup_menus(void)
        if (initialized)
        {
 #if TARGET_API_MAC_CARBON
-               EnableMenuItem(m, 4);
+               EnableMenuItem(m, ITEM_CLOSE);
 #else
-               EnableItem(m, 4);
+               EnableItem(m, ITEM_CLOSE);
 #endif
        }
 
@@ -3825,9 +5016,9 @@ static void setup_menus(void)
        if (initialized && character_generated)
        {
 #if TARGET_API_MAC_CARBON
-               EnableMenuItem(m, 5);
+               EnableMenuItem(m, ITEM_SAVE);
 #else
-               EnableItem(m, 5);
+               EnableItem(m, ITEM_SAVE);
 #endif
        }
 
@@ -3835,15 +5026,15 @@ static void setup_menus(void)
        if (TRUE)
        {
 #if TARGET_API_MAC_CARBON
-               EnableMenuItem(m, 7);
+               EnableMenuItem(m, ITEM_QUIT);
 #else
-               EnableItem(m, 7);
+               EnableItem(m, ITEM_QUIT);
 #endif
        }
 
 
        /* Edit menu */
-       m = GetMenuHandle(130);
+       m = GetMenuHandle(MENU_EDIT);
 
        /* Get menu size */
 #if TARGET_API_MAC_CARBON
@@ -3869,23 +5060,23 @@ static void setup_menus(void)
        if (!td)
        {
 #if TARGET_API_MAC_CARBON
-               EnableMenuItem(m, 1);
-               EnableMenuItem(m, 3);
-               EnableMenuItem(m, 4);
-               EnableMenuItem(m, 5);
-               EnableMenuItem(m, 6);
+               EnableMenuItem(m, ITEM_UNDO);
+               EnableMenuItem(m, ITEM_CUT);
+               EnableMenuItem(m, ITEM_COPY);
+               EnableMenuItem(m, ITEM_PASTE);
+               EnableMenuItem(m, ITEM_CLEAR);
 #else
-               EnableItem(m, 1);
-               EnableItem(m, 3);
-               EnableItem(m, 4);
-               EnableItem(m, 5);
-               EnableItem(m, 6);
+               EnableItem(m, ITEM_UNDO);
+               EnableItem(m, ITEM_CUT);
+               EnableItem(m, ITEM_COPY);
+               EnableItem(m, ITEM_PASTE);
+               EnableItem(m, ITEM_CLEAR);
 #endif
        }
 
 
        /* Font menu */
-       m = GetMenuHandle(131);
+       m = GetMenuHandle(MENU_FONT);
 
        /* Get menu size */
 #if TARGET_API_MAC_CARBON
@@ -3918,16 +5109,16 @@ static void setup_menus(void)
        {
 #if TARGET_API_MAC_CARBON
                /* Enable "bold" */
-               EnableMenuItem(m, 1);
+               EnableMenuItem(m, ITEM_BOLD);
 
                /* Enable "extend" */
-               EnableMenuItem(m, 2);
+               EnableMenuItem(m, ITEM_WIDE);
 
                /* Check the appropriate "bold-ness" */
-               if (td->font_face & bold) CheckMenuItem(m, 1, TRUE);
+               if (td->font_face & bold) CheckMenuItem(m, ITEM_BOLD, TRUE);
 
                /* Check the appropriate "wide-ness" */
-               if (td->font_face & extend) CheckMenuItem(m, 2, TRUE);
+               if (td->font_face & extend) CheckMenuItem(m, ITEM_WIDE, TRUE);
 
                /* Analyze fonts */
                for (i = 4; i <= n; i++)
@@ -3944,16 +5135,16 @@ static void setup_menus(void)
                }
 #else
                /* Enable "bold" */
-               EnableItem(m, 1);
+               EnableItem(m, ITEM_BOLD);
 
                /* Enable "extend" */
-               EnableItem(m, 2);
+               EnableItem(m, ITEM_WIDE);
 
                /* Check the appropriate "bold-ness" */
-               if (td->font_face & bold) CheckItem(m, 1, TRUE);
+               if (td->font_face & bold) CheckItem(m, ITEM_BOLD, TRUE);
 
                /* Check the appropriate "wide-ness" */
-               if (td->font_face & extend) CheckItem(m, 2, TRUE);
+               if (td->font_face & extend) CheckItem(m, ITEM_WIDE, TRUE);
 
                /* Analyze fonts */
                for (i = 4; i <= n; i++)
@@ -3973,7 +5164,7 @@ static void setup_menus(void)
 
 
        /* Size menu */
-       m = GetMenuHandle(132);
+       m = GetMenuHandle(MENU_SIZE);
 
        /* Get menu size */
 #if TARGET_API_MAC_CARBON
@@ -4001,23 +5192,18 @@ static void setup_menus(void)
                /* Analyze sizes */
                for (i = 1; i <= n; i++)
                {
-#if TARGET_API_MAC_CARBON
                        /* Analyze size */
                        GetMenuItemText(m, i, s);
                        s[s[0]+1] = '\0';
                        value = atoi((char*)(s+1));
 
+#if TARGET_API_MAC_CARBON
                        /* Enable the "real" sizes */
                        if (RealFont(td->font_id, value)) EnableMenuItem(m, i);
 
                        /* Check the current size */
                        if (td->font_size == value) CheckMenuItem(m, i, TRUE);
 #else
-                       /* Analyze size */
-                       GetMenuItemText(m, i, s);
-                       s[s[0]+1] = '\0';
-                       value = atoi((char*)(s+1));
-
                        /* Enable the "real" sizes */
                        if (RealFont(td->font_id, value)) EnableItem(m, i);
 
@@ -4029,7 +5215,7 @@ static void setup_menus(void)
 
 
        /* Windows menu */
-       m = GetMenuHandle(133);
+       m = GetMenuHandle(MENU_WINDOWS);
 
        /* Get menu size */
 #if TARGET_API_MAC_CARBON
@@ -4051,7 +5237,7 @@ static void setup_menus(void)
 
 
        /* Special menu */
-       m = GetMenuHandle(134);
+       m = GetMenuHandle(MENU_SPECIAL);
 
        /* Get menu size */
 #if TARGET_API_MAC_CARBON
@@ -4066,90 +5252,312 @@ static void setup_menus(void)
                /* Reset */
 #if TARGET_API_MAC_CARBON
                DisableMenuItem(m, i);
+
+#ifdef MAC_MPW
+               /* XXX Oh no, this removes submenu... */
+               if ((i != ITEM_SOUND) &&
+                   (i != ITEM_GRAPH) &&
+                   (i != ITEM_TILEWIDTH) &&
+                   (i != ITEM_TILEHEIGHT)) CheckMenuItem(m, i, FALSE);
+#else
+
                CheckMenuItem(m, i, FALSE);
+#endif
+
 #else
                DisableItem(m, i);
-               CheckItem(m, i, FALSE);
+
+               /* XXX Oh no, this removes submenu... */
+               if ((i != ITEM_SOUND) &&
+                   (i != ITEM_GRAPH) &&
+                   (i != ITEM_TILEWIDTH) &&
+                   (i != ITEM_TILEHEIGHT)) CheckItem(m, i, FALSE);
 #endif
        }
 
 #if TARGET_API_MAC_CARBON
        /* Item "arg_sound" */
-       EnableMenuItem(m, 1);
-       CheckMenuItem(m, 1, arg_sound);
+       EnableMenuItem(m, ITEM_SOUND);
+       {
+               MenuRef submenu;
 
-       /* Item "arg_graphics" */
-       EnableMenuItem(m, 2);
-       CheckMenuItem(m, 2, arg_graphics);
+#ifdef MAC_MPW
 
-       /* Item "arg_fiddle" */
-       EnableMenuItem(m, 4);
-       CheckMenuItem(m, 4, arg_fiddle);
+               /* MPW's Universal Interface is a bit out of date */
 
-       /* Item "arg_wizard" */
-       EnableMenuItem(m, 5);
-       CheckMenuItem(m, 5, arg_wizard);
+               /* Graphics submenu */
+               submenu = GetMenuHandle(SUBMENU_SOUND);
+
+#else
+
+               /* Graphics submenu */
+               (void)GetMenuItemHierarchicalMenu(m, ITEM_SOUND, &submenu);
+
+#endif
+
+               /* Get menu size */
+               n = CountMenuItems(submenu);
+
+               /* Reset menu */
+               for (i = 1; i <= n; i++)
+               {
+                       /* Reset */
+                       DisableMenuItem(submenu, i);
+                       CheckMenuItem(submenu, i, FALSE);
+               }
+
+               /* Item "Sound On/Off" */
+               EnableMenuItem(submenu, ITEM_USE_SOUND);
+               CheckMenuItem(submenu, ITEM_USE_SOUND, arg_sound);
+
+               /* Item "Sounf Config" */
+#ifndef MACH_O_CARBON
+               EnableMenuItem(submenu, ITEM_SOUND_SETTING);
+#endif
+       }
+
+       /* Item "Graphics" */
+       EnableMenuItem(m, ITEM_GRAPH);
+       {
+               MenuRef submenu;
+
+#ifdef MAC_MPW
+
+               /* MPW's Universal Interface is a bit out of date */
+
+               /* Graphics submenu */
+               submenu = GetMenuHandle(SUBMENU_GRAPH);
+
+#else
+
+               /* Graphics submenu */
+               (void)GetMenuItemHierarchicalMenu(m, ITEM_GRAPH, &submenu);
+
+#endif
+
+               /* Get menu size */
+               n = CountMenuItems(submenu);
+
+               /* Reset menu */
+               for (i = 1; i <= n; i++)
+               {
+                       /* Reset */
+                       DisableMenuItem(submenu, i);
+                       CheckMenuItem(submenu, i, FALSE);
+               }
+
+               /* Item "None" */
+               EnableMenuItem(submenu, ITEM_NONE);
+               CheckMenuItem(submenu, ITEM_NONE, (graf_mode == GRAF_MODE_NONE));
+
+               /* Item "8x8" */
+               EnableMenuItem(submenu, ITEM_8X8);
+               CheckMenuItem(submenu, ITEM_8X8, (graf_mode == GRAF_MODE_8X8));
+
+               /* Item "16x16" */
+               EnableMenuItem(submenu, ITEM_16X16);
+               CheckMenuItem(submenu, ITEM_16X16, (graf_mode == GRAF_MODE_16X16));
+
+               /* Item "Big tiles" */
+               EnableMenuItem(submenu, ITEM_BIGTILE);
+               CheckMenuItem(submenu, ITEM_BIGTILE, arg_bigtile);
+       }
+
+       /* Item "TileWidth" */
+       EnableMenuItem(m, ITEM_TILEWIDTH);
+       {
+               MenuRef submenu;
+
+#ifdef MAC_MPW
+
+               /* MPW's Universal Interface is a bit out of date */
+
+               /* TIleWidth submenu */
+               submenu = GetMenuHandle(SUBMENU_TILEWIDTH);
+
+#else
+
+               /* TileWidth submenu */
+               (void)GetMenuItemHierarchicalMenu(m, ITEM_TILEWIDTH, &submenu);
 
-       /* Item "SoundSetting" */
-       EnableMenuItem(m, 7);
+#endif
+
+               /* Get menu size */
+               n = CountMenuItems(submenu);
+
+               /* Reset menu */
+               for (i = 1; i <= n; i++)
+               {
+                       /* Reset */
+                       DisableMenuItem(submenu, i);
+                       CheckMenuItem(submenu, i, FALSE);
+               }
+
+               /* Active window */
+               if (td)
+               {
+                       /* Analyze sizes */
+                       for (i = 1; i <= n; i++)
+                       {
+                               /* Analyze size */
+                               /* GetMenuItemText(m,i,s); */
+                               GetMenuItemText(submenu, i, s);
+                               s[s[0]+1] = '\0';
+                               value = atoi((char*)(s+1));
+
+                               /* Enable */
+                               if (value >= td->font_wid) EnableMenuItem(submenu, i);
+
+                               /* Check the current size */
+                               if (td->tile_wid == value) CheckMenuItem(submenu, i, TRUE);
+                       }
+               }
+       }
+
+       /* Item "TileHeight" */
+       EnableMenuItem(m, ITEM_TILEHEIGHT);
+       {
+               MenuRef submenu;
+
+#ifdef MAC_MPW
+
+               /* MPW's Universal Interface is a bit out of date */
+
+               /* TileHeight submenu */
+               submenu = GetMenuHandle(SUBMENU_TILEHEIGHT);
+
+#else
+
+               /* TileWidth submenu */
+               (void)GetMenuItemHierarchicalMenu(m, ITEM_TILEHEIGHT, &submenu);
+
+#endif
+
+               /* Get menu size */
+               n = CountMenuItems(submenu);
+
+               /* Reset menu */
+               for (i = 1; i <= n; i++)
+               {
+                       /* Reset */
+                       DisableMenuItem(submenu, i);
+                       CheckMenuItem(submenu, i, FALSE);
+               }
+
+               /* Active window */
+               if (td)
+               {
+                       /* Analyze sizes */
+                       for (i = 1; i <= n; i++)
+                       {
+                               /* Analyze size */
+                               /* GetMenuItemText(m,i,s); */
+                               GetMenuItemText(submenu, i, s);
+                               s[s[0]+1] = '\0';
+                               value = atoi((char*)(s+1));
+
+                               /* Enable */
+                               if (value >= td->font_hgt) EnableMenuItem(submenu, i);
+
+                               /* Check the current size */
+                               if (td->tile_hgt == value) CheckMenuItem(submenu, i, TRUE);
+                       }
+               }
+       }
+
+       /* Item "arg_fiddle" */
+       EnableMenuItem(m, ITEM_FIDDLE);
+       CheckMenuItem(m, ITEM_FIDDLE, arg_fiddle);
 
-       /* Item NewStyle Graphics */
-       EnableMenuItem(m, 8);
-       CheckMenuItem(m, 8, use_newstyle_graphics);
+       /* Item "arg_wizard" */
+       EnableMenuItem(m, ITEM_WIZARD);
+       CheckMenuItem(m, ITEM_WIZARD, arg_wizard);
 
-       /* Item Bigtile Mode */
-       EnableMenuItem(m, 9);
-       CheckMenuItem(m, 9, arg_bigtile);
 #else
        /* Item "arg_sound" */
-       EnableItem(m, 1);
-       CheckItem(m, 1, arg_sound);
+       EnableItem(m, ITEM_SOUND);
 
        /* Item "arg_graphics" */
-       EnableItem(m, 2);
-       CheckItem(m, 2, arg_graphics);
+       EnableItem(m, ITEM_GRAPH);
+
+       /* Item "TileWidth" */
+       EnableItem(m, ITEM_TILEWIDTH);
+
+       /* Item "TileHeight" */
+       EnableItem(m, ITEM_TILEHEIGHT);
 
        /* Item "arg_fiddle" */
-       EnableItem(m, 4);
-       CheckItem(m, 4, arg_fiddle);
+       EnableItem(m, ITEM_FIDDLE);
+       CheckItem(m, ITEM_FIDDLE, arg_fiddle);
 
        /* Item "arg_wizard" */
-       EnableItem(m, 5);
-       CheckItem(m, 5, arg_wizard);
+       EnableItem(m, ITEM_WIZARD);
+       CheckItem(m, ITEM_WIZARD, arg_wizard);
 
-       /* Item "SoundSetting" */
-       EnableItem(m, 7);
+       /* Sounds submenu */
+       m = GetMenuHandle(SUBMENU_SOUND);
 
-       /* Item NewStyle Graphics */
-       EnableItem(m, 8);
-       CheckItem(m, 8, use_newstyle_graphics);
+       /* Get menu size */
+       n = CountMItems(m);
 
-       /* Item Bigtile Mode */
-       EnableItem(m, 9);
-       CheckItem(m, 9, arg_bigtile);
-#endif
+       /* Reset menu */
+       for (i = 1; i <= n; i++)
+       {
+               /* Reset */
+               DisableItem(m, i);
+               CheckItem(m, i, FALSE);
+       }
+       
+       /* Item "Sound On/Off" */
+       EnableItem(m, ITEM_USE_SOUND);
+       CheckItem(m, ITEM_USE_SOUND, arg_sound);
 
-       /* TileWidth menu */
-       m = GetMenuHandle(135);
+       /* Item "Sound Config" */
+       EnableItem(m, ITEM_SOUND_SETTING);
+
+       /* Graphics submenu */
+       m = GetMenuHandle(SUBMENU_GRAPH);
+
+       /* Get menu size */
+       n = CountMItems(m);
+
+       /* Reset menu */
+       for (i = 1; i <= n; i++)
+       {
+               /* Reset */
+               DisableItem(m, i);
+               CheckItem(m, i, FALSE);
+       }
+       
+       /* Item "None" */
+       EnableItem(m, ITEM_NONE);
+       CheckItem(m, ITEM_NONE, (graf_mode == GRAF_MODE_NONE));
+
+       /* Item "8x8" */
+       EnableItem(m, ITEM_8X8);
+       CheckItem(m, ITEM_8X8, (graf_mode == GRAF_MODE_8X8));
+
+       /* Item "16x16" */
+       EnableItem(m, ITEM_16X16);
+       CheckItem(m, ITEM_16X16, (graf_mode == GRAF_MODE_16X16));
+
+       /* Item "Bigtile" */
+       EnableItem(m, ITEM_BIGTILE);
+       CheckItem(m, ITEM_BIGTILE, arg_bigtile);
+
+
+       /* TIleWidth submenu */
+       m = GetMenuHandle(SUBMENU_TILEWIDTH);
 
        /* Get menu size */
-#if TARGET_API_MAC_CARBON
-       n = CountMenuItems(m);
-#else
        n = CountMItems(m);
-#endif
 
        /* Reset menu */
        for (i = 1; i <= n; i++)
        {
                /* Reset */
-#if TARGET_API_MAC_CARBON
-               DisableMenuItem(m, i);
-               CheckMenuItem(m, i, FALSE);
-#else
                DisableItem(m, i);
                CheckItem(m, i, FALSE);
-#endif
        }
 
        /* Active window */
@@ -4164,44 +5572,27 @@ static void setup_menus(void)
                        s[s[0]+1] = '\0';
                        value = atoi((char*)(s+1));
 
-#if TARGET_API_MAC_CARBON
-                       /* Enable */
-                       EnableMenuItem(m, i);
-
-                       /* Check the current size */
-                       if (td->tile_wid == value) CheckMenuItem(m, i, TRUE);
-#else
                        /* Enable */
-                       EnableItem(m, i);
+                       if (value >= td->font_wid) EnableItem(m, i);
 
                        /* Check the current size */
                        if (td->tile_wid == value) CheckItem(m, i, TRUE);
-#endif
                }
        }
 
 
-       /* TileHeight menu */
-       m = GetMenuHandle(136);
+       /* TileHeight submenu */
+       m = GetMenuHandle(SUBMENU_TILEHEIGHT);
 
        /* Get menu size */
-#if TARGET_API_MAC_CARBON
-       n = CountMenuItems(m);
-#else
        n = CountMItems(m);
-#endif
 
        /* Reset menu */
        for (i = 1; i <= n; i++)
        {
                /* Reset */
-#if TARGET_API_MAC_CARBON
-               DisableMenuItem(m, i);
-               CheckMenuItem(m, i, FALSE);
-#else
                DisableItem(m, i);
                CheckItem(m, i, FALSE);
-#endif
        }
 
        /* Active window */
@@ -4215,21 +5606,15 @@ static void setup_menus(void)
                        s[s[0]+1] = '\0';
                        value = atoi((char*)(s+1));
 
-#if TARGET_API_MAC_CARBON
-                       /* Enable */
-                       EnableMenuItem(m, i);
-
-                       /* Check the current size */
-                       if (td->tile_hgt == value) CheckMenuItem(m, i, TRUE);
-#else
                        /* Enable */
-                       EnableItem(m, i);
+                       if (value >= td->font_hgt) EnableItem(m, i);
 
                        /* Check the current size */
                        if (td->tile_hgt == value) CheckItem(m, i, TRUE);
-#endif
                }
        }
+#endif
+
 }
 
 
@@ -4274,11 +5659,11 @@ static void menu(long mc)
        switch (menuid)
        {
                /* Apple Menu */
-               case 128:
+               case MENU_APPLE:
                {
                        /* About Angband... */
 #if TARGET_API_MAC_CARBON
-                       if (selection == 1)
+                       if (selection == ITEM_ABOUT)
                        {
                                DialogPtr dialog;
                                short item_hit;
@@ -4306,7 +5691,7 @@ static void menu(long mc)
                                break;
                        }
 #else
-                       if (selection == 1)
+                       if (selection == ITEM_ABOUT)
                        {
                                DialogPtr dialog;
                                Rect r;
@@ -4324,41 +5709,40 @@ static void menu(long mc)
                        }
 
                        /* Desk accessory */
-                       /* GetMenuItemText(GetMHandle(128),selection,s); */
-                       GetMenuItemText(GetMenuHandle(128), selection, s);
+                       GetMenuItemText(GetMenuHandle(MENU_APPLE), selection, s);
                        OpenDeskAcc(s);
                        break;
 #endif
                }
 
                /* File Menu */
-               case 129:
+               case MENU_FILE:
                {
                        switch (selection)
                        {
                                /* New */
-                               case 1:
+                               case ITEM_NEW:
                                {
                                        do_menu_file_new();
                                        break;
                                }
 
                                /* Open... */
-                               case 2:
+                               case ITEM_OPEN:
                                {
                                        do_menu_file_open(FALSE);
                                        break;
                                }
 
                                /* Import... */
-                               case 3:
+                               case ITEM_IMPORT:
                                {
                                        do_menu_file_open(TRUE);
                                        break;
                                }
 
                                /* Close */
-                               case 4:
+                               case ITEM_CLOSE:
                                {
                                        /* No window */
                                        if (!td) break;
@@ -4376,7 +5760,7 @@ static void menu(long mc)
                                }
 
                                /* Save */
-                               case 5:
+                               case ITEM_SAVE:
                                {
                                        if (!can_save){
 #ifdef JP
@@ -4397,7 +5781,7 @@ static void menu(long mc)
                                }
 
                                /* Quit (with save) */
-                               case 7:
+                               case ITEM_QUIT:
                                {
                                        /* Save the game (if necessary) */
                                        if (game_in_progress && character_generated)
@@ -4430,14 +5814,14 @@ static void menu(long mc)
                }
 
                /* Edit menu */
-               case 130:
+               case MENU_EDIT:
                {
                        /* Unused */
                        break;
                }
 
                /* Font menu */
-               case 131:
+               case MENU_FONT:
                {
                        /* Require a window */
                        if (!td) break;
@@ -4449,7 +5833,7 @@ static void menu(long mc)
                        activate(td->w);
 
                        /* Toggle the "bold" setting */
-                       if (selection == 1)
+                       if (selection == ITEM_BOLD)
                        {
                                /* Toggle the setting */
                                if (td->font_face & bold)
@@ -4476,7 +5860,7 @@ static void menu(long mc)
                        }
 
                        /* Toggle the "wide" setting */
-                       if (selection == 2)
+                       if (selection == ITEM_WIDE)
                        {
                                /* Toggle the setting */
                                if (td->font_face & extend)
@@ -4503,7 +5887,7 @@ static void menu(long mc)
                        }
 
                        /* Get a new font name */
-                       GetMenuItemText(GetMenuHandle(131), selection, s);
+                       GetMenuItemText(GetMenuHandle(MENU_FONT), selection, s);
                        GetFNum(s, &fid);
 
                        /* Save the new font id */
@@ -4555,7 +5939,7 @@ static void menu(long mc)
                }
 
                /* Size menu */
-               case 132:
+               case MENU_SIZE:
                {
                        if (!td) break;
 
@@ -4565,7 +5949,7 @@ static void menu(long mc)
                        /* Activate */
                        activate(td->w);
 
-                       GetMenuItemText(GetMenuHandle(132), selection, s);
+                       GetMenuItemText(GetMenuHandle(MENU_SIZE), selection, s);
                        s[s[0]+1]=0;
                        td->font_size = atoi((char*)(s+1));
 
@@ -4587,7 +5971,7 @@ static void menu(long mc)
                }
 
                /* Window menu */
-               case 133:
+               case MENU_WINDOWS:
                {
                        /* Parse */
                        i = selection - 1;
@@ -4617,11 +6001,32 @@ static void menu(long mc)
                }
 
                /* Special menu */
-               case 134:
+               case MENU_SPECIAL:
+               {
+                       switch (selection)
+                       {
+                               case ITEM_FIDDLE:
+                               {
+                                       arg_fiddle = !arg_fiddle;
+                                       break;
+                               }
+
+                               case ITEM_WIZARD:
+                               {
+                                       arg_wizard = !arg_wizard;
+                                       break;
+                               }
+                       }
+
+                       break;
+               }
+
+               /* Sounds submenu */
+               case SUBMENU_SOUND:
                {
                        switch (selection)
                        {
-                               case 1:
+                               case ITEM_USE_SOUND:
                                {
                                        /* Toggle arg_sound */
                                        arg_sound = !arg_sound;
@@ -4632,75 +6037,48 @@ static void menu(long mc)
                                        break;
                                }
 
-                               case 2:
+                               case ITEM_SOUND_SETTING:
                                {
-                                       /* Toggle arg_graphics */
-                                       arg_graphics = !arg_graphics;
-                                       if( arg_graphics == true ){
-                                               ANGBAND_GRAF = "old";
-                                               arg_newstyle_graphics = false;
-                                               grafWidth = grafHeight = 8;
-                                               pictID = 1001;
-                                       }
-
-                                       /* Hack -- Force redraw */
-                                       Term_key_push(KTRL('R'));
+                                       SoundConfigDLog();
 
                                        break;
                                }
+                       }
 
-                               case 4:
-                               {
-                                       arg_fiddle = !arg_fiddle;
-                                       break;
-                               }
+                       break;
+               }
 
-                               case 5:
+               /* Graphics submenu */
+               case SUBMENU_GRAPH:
+               {
+                       switch (selection)
+                       {
+                               case ITEM_NONE:
                                {
-                                       arg_wizard = !arg_wizard;
+                                       graf_mode_req = GRAF_MODE_NONE;
+
                                        break;
                                }
 
-                               case 7:
+                               case ITEM_8X8:
                                {
-                                       SoundConfigDLog();
+                                       graf_mode_req = GRAF_MODE_8X8;
+
                                        break;
                                }
-                               case 8:
+
+                               case ITEM_16X16:
                                {
-                                       if (streq(ANGBAND_GRAF, "old"))
-                                       {
-                                               ANGBAND_GRAF = "new";
-                                               arg_newstyle_graphics = true;
-                                               grafWidth = grafHeight = 16;
-                                               pictID = 1002;
-                                       }
-                                       else
-                                       {
-                                               ANGBAND_GRAF = "old";
-                                               arg_newstyle_graphics = false;
-                                               grafWidth = grafHeight = 8;
-                                               pictID = 1001;
-                                       }
+                                       graf_mode_req = GRAF_MODE_16X16;
 
-                                       /* Hack -- Force redraw */
-                                       Term_key_push(KTRL('R'));
                                        break;
                                }
 
-                               case 9: /* bigtile mode */
+                               case ITEM_BIGTILE:
                                {
+                                       term *old = Term;
                                        term_data *td = &data[0];
 
-                                       if (!can_save){
-#ifdef JP
-                                               plog("º£¤ÏÊѹ¹½ÐÍè¤Þ¤»¤ó¡£");
-#else
-                                               plog("You may not do that right now.");
-#endif
-                                               break;
-                                       }
-
                                        /* Toggle "arg_bigtile" */
                                        arg_bigtile = !arg_bigtile;
 
@@ -4710,16 +6088,21 @@ static void menu(long mc)
                                        /* Resize the term */
                                        Term_resize(td->cols, td->rows);
 
+                                       /* Activate old */
+                                       Term_activate(old);
+
                                        break;
                                }
-
                        }
 
+                       /* Hack -- Force redraw */
+                       Term_key_push(KTRL('R'));
+
                        break;
                }
 
-               /* TileWidth menu */
-               case 135:
+               /* TileWidth submenu */
+               case SUBMENU_TILEWIDTH:
                {
                        if (!td) break;
 
@@ -4729,7 +6112,8 @@ static void menu(long mc)
                        /* Activate */
                        activate(td->w);
 
-                       GetMenuItemText(GetMenuHandle(135), selection, s);
+                       /* Analyse value */
+                       GetMenuItemText(GetMenuHandle(SUBMENU_TILEWIDTH), selection, s);
                        s[s[0]+1]=0;
                        td->tile_wid = atoi((char*)(s+1));
 
@@ -4746,8 +6130,8 @@ static void menu(long mc)
                        break;
                }
 
-               /* TileHeight menu */
-               case 136:
+               /* TileHeight submenu */
+               case SUBMENU_TILEHEIGHT:
                {
                        if (!td) break;
 
@@ -4757,7 +6141,8 @@ static void menu(long mc)
                        /* Activate */
                        activate(td->w);
 
-                       GetMenuItemText(GetMenuHandle(136), selection, s);
+                       /* Analyse value */
+                       GetMenuItemText(GetMenuHandle(SUBMENU_TILEHEIGHT), selection, s);
                        s[s[0]+1]=0;
                        td->tile_hgt = atoi((char*)(s+1));
 
@@ -4824,6 +6209,7 @@ static pascal OSErr AEH_Quit(const AppleEvent *theAppleEvent,
 {
 #pragma unused(reply, handlerRefCon)
 #if TARGET_API_MAC_CARBON
+#pragma unused(theAppleEvent)
 
        /* Save the game (if necessary) */
        if (game_in_progress && character_generated)
@@ -4924,6 +6310,13 @@ static pascal OSErr AEH_Open(const AppleEvent *theAppleEvent,
        /* Ignore non 'SAVE' files */
        if (myFileInfo.fdType != 'SAVE') return noErr;
 
+#ifdef MACH_O_CARBON
+
+       /* Extract a file name */
+       (void)spec_to_path(&myFSS, savefile, sizeof(savefile));
+
+#else
+
        /* XXX XXX XXX Extract a file name */
        PathNameFromDirID(myFSS.parID, myFSS.vRefNum, (StringPtr)savefile);
        pstrcat((StringPtr)savefile, (StringPtr)&myFSS.name);
@@ -4931,6 +6324,8 @@ static pascal OSErr AEH_Open(const AppleEvent *theAppleEvent,
        /* Convert the string */
        ptocstr((StringPtr)savefile);
 
+#endif /* MACH_O_CARBON */
+
        /* Delay actual open */
        open_when_ready = TRUE;
 
@@ -5497,7 +6892,7 @@ static vptr hook_rpanic(huge size)
 
 #pragma unused (size)
 
-       vptr mem = NULL;
+       /* vptr mem = NULL; */
 
        /* Free the lifeboat */
        if (lifeboat)
@@ -5541,6 +6936,13 @@ static void hook_quit(cptr str)
        /* Warning if needed */
        if (str) mac_warning(str);
 
+#ifdef USE_ASYNC_SOUND
+
+       /* Clean up sound support */
+       cleanup_sound();
+
+#endif /* USE_ASYNC_SOUND */
+
        /* Write a preference file */
        save_pref_file();
 
@@ -5600,12 +7002,14 @@ static void init_stuff(void)
 {
        int i;
 
+#if !TARGET_API_MAC_CARBON
        short vrefnum;
        long drefnum;
        long junk;
 
        SFTypeList types;
        SFReply reply;
+#endif
 
        Rect r;
        Point topleft;
@@ -5641,7 +7045,11 @@ static void init_stuff(void)
 
 
        /* Default to the "lib" folder with the application */
+#ifdef MACH_O_CARBON
+       if (locate_lib(path, sizeof(path)) == NULL) quit(NULL);
+#else
        refnum_to_name(path, app_dir, app_vol, (char*)("\plib:"));
+#endif
 
 
        /* Check until done */
@@ -5788,7 +7196,7 @@ static void init_stuff(void)
 /*
  * Macintosh Main loop
  */
-void main(void)
+int main(void)
 {
        EventRecord tempEvent;
        int numberOfMasters = 10;
@@ -5842,6 +7250,19 @@ void main(void)
 
 # else
 
+#if TARGET_API_MAC_CARBON
+
+       {
+               OSErr err;
+               long response;
+
+               /* Check for existence of Carbon */
+               err = Gestalt(gestaltCarbonVersion, &response);
+
+               if (err != noErr) quit("This program requires Carbon API");
+       }
+
+#else
        /* Block */
        if (TRUE)
        {
@@ -5898,7 +7319,8 @@ void main(void)
                }
        }
 
-# endif
+#endif /* CARBON */
+#endif
 
 #endif /* ANGBAND_LITE_MAC */
 
@@ -5934,12 +7356,13 @@ void main(void)
                              0L, FALSE);
 #endif
 
+#ifndef MACH_O_CARBON
        /* Find the current application */
        SetupAppDir();
-
+#endif
 
        /* Mark ourself as the file creator */
-       _fcreator = 'Heng';
+       _fcreator = ANGBAND_CREATOR;
 
        /* Default to saving a "text" file */
        _ftype = 'TEXT';
@@ -5979,9 +7402,13 @@ void main(void)
        /* Prepare the windows */
        init_windows();
 
+#ifndef MACH_O_CARBON
+
        init_sound();
 
        init_graf();
+
+#endif
        
        /* Hack -- process all events */
        while (CheckEvents(TRUE)) /* loop */;
@@ -6001,12 +7428,22 @@ void main(void)
        /* Mega-Hack -- Allocate a "lifeboat" */
        lifeboat = NewPtr(16384);
 
+#ifdef USE_QT_SOUND
+
+       /* Load sound effect resources */
+       load_sounds();
+
+#endif /* USE_QT_SOUND */
+
        /* Note the "system" */
        ANGBAND_SYS = "mac";
 
        /* Initialize */
        init_stuff();
 
+       /* Catch nasty signals */
+       signals_init();
+
        /* Initialize */
        init_angband();