From: macband Date: Tue, 17 Aug 2004 02:15:28 +0000 (+0000) Subject: メニューの構成を変更。 X-Git-Tag: v2.1.2~338 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=352facc04c49eaeb4b011779660a6de0ebe1f92e;p=hengband%2Fhengband.git メニューの構成を変更。 OSXバイナリではタイルとサウンドをパッケージに含められるように変更。 タイルはpngフォーマット、サウンドはwavフォーマットが利用出来る。 --- diff --git a/src/main-mac.c b/src/main-mac.c index 03c12a1a4..a7256c973 100644 --- a/src/main-mac.c +++ b/src/main-mac.c @@ -183,11 +183,6 @@ #endif /* MACH_O_CARBON */ /* - * Use rewritten asynchronous sound player - */ -#define USE_ASYNC_SOUND - -/* * Cleaning up a couple of things to make these easier to change --AR */ #ifdef JP @@ -237,6 +232,17 @@ */ # 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 */ @@ -458,1645 +464,1793 @@ AEEventHandlerUPP AEH_Open_UPP; #endif -# 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 */ - - /* - * Number of channels in the channel pool + * 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 */ #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; +static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname) +{ + CInfoPBRec pb; + int err; + int i, j; -/* - * Data handles containing sound samples - */ -static SndListHandle samples[SOUND_MAX]; + char res[1000]; + + FSSpec spec; + short vref; + long dirID; + + i=999; -/* - * Reference counts of sound samples - */ -static SInt16 sample_refs[SOUND_MAX]; + res[i]=0; i--; + for (j=1; j<=fname[0]; j++) + { + res[i-fname[0]+j] = fname[j]; + } + i-=fname[0]; + vref = vrefnum; + dirID = refnum; -/* - * 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 % */ + while (1) + { + pb.dirInfo.ioDrDirID=pb.dirInfo.ioDrParID; + err = FSMakeFSSpec( vref, dirID, "\p", &spec ); + + if( err != noErr ) + break; + + res[i] = ':'; i--; + for (j=1; j<=spec.name[0]; j++) + { + res[i-spec.name[0]+j] = spec.name[j]; + } + i -= spec.name[0]; + + dirID = spec.parID; + } -/* I'm just too lazy to write a panel for this XXX XXX */ -static SInt16 sound_volume = SOUND_VOLUME_MAX; + /* Extract the result */ + for (j = 0, i++; res[i]; j++, i++) buf[j] = res[i]; + buf[j] = 0; +} +#else +static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname) +{ + DirInfo pb; + Str255 name; + int err; + int i, j; -#ifdef USE_QT_SOUND + char res[1000]; -/* - * 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; + i=999; - /* Find resource (=file) in the current bundle */ - res_url = CFBundleCopyResourceURL( - CFBundleGetMainBundle(), base_name, type_name, NULL); + res[i]=0; i--; + for (j=1; j<=fname[0]; j++) + { + res[i-fname[0]+j] = fname[j]; + } + i-=fname[0]; - /* Oops */ - if (res_url == NULL) return (false); + pb.ioCompletion=NULL; + pb.ioNamePtr=name; + pb.ioVRefNum=vrefnum; + pb.ioDrParID=refnum; + pb.ioFDirIndex=-1; - /* Convert CFURL to FSRef */ - (void)CFURLGetFSRef(res_url, &ref); + while (1) + { + pb.ioDrDirID=pb.ioDrParID; + err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE); + res[i] = ':'; i--; + for (j=1; j<=name[0]; j++) + { + res[i-name[0]+j] = name[j]; + } + i -= name[0]; - /* Convert FSRef to FSSpec */ - (void)FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL); + if (pb.ioDrDirID == fsRtDirID) break; + } - /* Free allocated CF data */ - CFRelease(res_url); + /* Extract the result */ + for (j = 0, i++; res[i]; j++, i++) buf[j] = res[i]; + buf[j] = 0; +} +#endif - /* Success */ - return (true); +#if TARGET_API_MAC_CARBON +pascal OSErr FSpLocationFromFullPath(short fullPathLength, + const void *fullPath, + FSSpec *spec) +{ + AliasHandle alias; + OSErr result; + Boolean wasChanged; + Str32 nullString; + + /* Create a minimal alias from the full pathname */ + nullString[0] = 0; /* null string to indicate no zone or server name */ + result = NewAliasMinimalFromFullPath(fullPathLength, fullPath, nullString, nullString, &alias); + if ( result == noErr ) + { + /* Let the Alias Manager resolve the alias. */ + result = ResolveAlias(NULL, alias, spec, &wasChanged); + + /* work around Alias Mgr sloppy volume matching bug */ + if ( spec->vRefNum == 0 ) + { + /* invalidate wrong FSSpec */ + spec->parID = 0; + spec->name[0] = 0; + result = nsvErr; + } + DisposeHandle((Handle)alias); /* Free up memory used */ + } + return ( result ); } +#endif -/* - * 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 - */ +#if 0 /* - * (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*) + * XXX XXX XXX Allow the system to ask us for a filename */ -static void load_sounds(void) +static bool askfor_file(char *buf, int len) { - OSErr err; - int i; + SFReply reply; + Str255 dflt; + Point topleft; + short vrefnum; + long drefnum, junk; - /* Start QuickTime */ - err = EnterMovies(); + /* Default file name */ + sprintf((char*)dflt + 1, "%s's description", buf); + dflt[0] = strlen((char*)dflt + 1); - /* Error */ - if (err != noErr) return; + /* Ask for a file name */ + topleft.h=(qd.screenBits.bounds.left+qd.screenBits.bounds.right)/2-344/2; + topleft.v=(2*qd.screenBits.bounds.top+qd.screenBits.bounds.bottom)/3-188/2; + SFPutFile(topleft, "\pSelect a filename:", dflt, NULL, &reply); + /* StandardPutFile("\pSelect a filename:", dflt, &reply); */ - /* - * 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++) + /* Process */ + if (reply.good) { - /* 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; + int fc; - /* Allocate CFString with the name of sound event to be processed */ - name = CFStringCreateWithCString(NULL, angband_sound_name[i], - kTextEncodingUS_ASCII); + /* Get info */ + GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk); - /* Error */ - if (name == NULL) continue; + /* Extract the name */ + refnum_to_name(buf, drefnum, vrefnum, (char*)reply.fName); - /* Find sound sample resource with the same name */ - res = get_resource_spec(name, CFSTR("wav"), &spec); + /* Success */ + return (TRUE); + } - /* Free the reference to CFString */ - CFRelease(name); + /* Failure */ + return (FALSE); +} - /* Error */ - if (!res) continue; +#endif - /* Open the sound file */ - err = OpenMovieFile(&spec, &file_id, fsRdPerm); +#if !TARGET_API_MAC_CARBON +static void local_to_global( Rect *r ) +{ + Point temp; + + temp.h = r->left; + temp.v = r->top; + + LocalToGlobal( &temp ); + + r->left = temp.h; + r->top = temp.v; + + temp.h = r->right; + temp.v = r->bottom; + + LocalToGlobal( &temp ); + + r->right = temp.h; + r->bottom = temp.v; +} +#endif /* !TARGET_API_MAC_CARBON */ - /* Error */ - if (err != noErr) continue; +static void global_to_local( Rect *r ) +{ + Point temp; + + temp.h = r->left; + temp.v = r->top; + + GlobalToLocal( &temp ); + + r->left = temp.h; + r->top = temp.v; + + temp.h = r->right; + temp.v = r->bottom; + + GlobalToLocal( &temp ); + + r->right = temp.h; + r->bottom = temp.v; +} - /* Create Movie from the file */ - err = NewMovieFromFile(&movie, file_id, &res_id, movie_name, - newMovieActive, NULL); - /* Error */ - if (err != noErr) goto close_file; +#ifdef MAC_MPW - /* Get the first track of the movie */ - track = GetMovieIndTrackType(movie, 1, AudioMediaCharacteristic, - movieTrackCharacteristic | movieTrackEnabledOnly ); +/* + * Convert pathname to an appropriate format, because MPW's + * CarbonStdCLib chose to use system's native path format, + * making our lives harder to create binaries that run on + * OS 8/9 and OS X :( -- pelpel + */ +void convert_pathname(char* path) +{ + char buf[1024]; - /* Error */ - if (track == NULL) goto close_movie; + /* Nothing has to be done for CarbonLib on Classic */ + if (mac_os_version >= 0x1000) + { + /* Convert to POSIX style */ + ConvertHFSPathToUnixPath(path, buf); - /* Allocate a handle to store sample */ - h = NewHandle(0); + /* Copy the result back */ + strcpy(path, buf); + } - /* Error */ - if (h == NULL) goto close_track; + /* Done. */ + return; +} - /* Dump the sample into the handle */ - err = PutMovieIntoTypedHandle(movie, track, soundListRsrc, h, 0, - GetTrackDuration(track), 0L, NULL); +# ifdef CHECK_MODIFICATION_TIME - /* Success */ - if (err == noErr) - { - /* Store the handle in the sample list */ - samples[i] = (SndListHandle)h; - } +/* + * Although there is no easy way to emulate fstat in the old interface, + * we still can do stat-like things, because Mac OS is an OS. + */ +static int get_modification_time(cptr path, u32b *mod_time) +{ + CInfoPBRec pb; + Str255 pathname; + int i; - /* Failure */ - else - { - /* Free unused handle */ - DisposeHandle(h); - } + /* Paranoia - make sure the pathname fits in Str255 */ + i = strlen(path); + if (i > 255) return (-1); - /* Free the track */ - close_track: DisposeMovieTrack(track); + /* Convert pathname to a Pascal string */ + strncpy((char *)pathname + 1, path, 255); + pathname[0] = i; - /* Free the movie */ - close_movie: DisposeMovie(movie); + /* Set up parameter block */ + pb.hFileInfo.ioNamePtr = pathname; + pb.hFileInfo.ioFDirIndex = 0; + pb.hFileInfo.ioVRefNum = app_vol; + pb.hFileInfo.ioDirID = 0; - /* Close the movie file */ - close_file: CloseMovieFile(file_id); - } + /* Get catalog information of the file */ + if (PBGetCatInfoSync(&pb) != noErr) return (-1); - /* Stop QuickTime */ - ExitMovies(); + /* Set modification date and time */ + *mod_time = pb.hFileInfo.ioFlMdDat; + + /* Success */ + return (0); } -#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) + * A (non-Mach-O) Mac OS version of check_modification_time, for those + * compilers without good enough POSIX-compatibility libraries XXX XXX */ -static SndListHandle find_sound(int num) +errr check_modification_date(int fd, cptr template_file) { - Str255 sound; +#pragma unused(fd) + u32b txt_stat, raw_stat; + char *p; + char fname[32]; + char buf[1024]; - /* Get the proper sound name */ - strnfmt((char*)sound + 1, 255, "%.16s.wav", angband_sound_name[num]); - sound[0] = strlen((char*)sound + 1); + /* Build the file name */ + path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, template_file); - /* Obtain resource XXX XXX XXX */ - return ((SndListHandle)GetNamedResource('snd ', sound)); -} + /* XXX XXX XXX */ + convert_pathname(buf); -#endif /* USE_QT_SOUND */ + /* Obtain modification time */ + if (get_modification_time(buf, &txt_stat)) return (-1); + /* XXX Build filename of the corresponding *.raw file */ + strnfmt(fname, sizeof(fname), "%s", template_file); -/* - * Clean up sound support - to be called when the game exits. - * - * Globals referenced: channels[], samples[], sample_refs[]. - */ -static void cleanup_sound(void) -{ - int i; + /* Find last '.' */ + p = strrchr(fname, '.'); - /* No need to clean it up */ - if (!channel_initialised) return; + /* Can't happen */ + if (p == NULL) return (-1); - /* Dispose channels */ - for (i = 0; i < MAX_CHANNELS; i++) - { - /* Drain sound commands and free the channel */ - SndDisposeChannel(channels[i], TRUE); - } + /* Substitute ".raw" for ".txt" */ + strcpy(p, ".raw"); - /* 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]); - } + /* Build the file name of the raw file */ + path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, fname); -#ifndef USE_QT_SOUND + /* XXX XXX XXX */ + convert_pathname(buf); - /* Release it */ - if (samples[i]) ReleaseResource((Handle)samples[i]); -#else + /* Obtain modification time */ + if (get_modification_time(buf, &raw_stat)) return (-1); - /* Free handle */ - if (samples[i]) DisposeHandle((Handle)samples[i]); -#endif /* !USE_QT_SOUND */ - } + /* Ensure the text file is not newer than the raw file */ + if (txt_stat > raw_stat) return (-1); + + /* Keep using the current .raw file */ + return (0); } +# endif /* CHECK_MODIFICATION_TIME */ + +#endif /* MAC_MPW */ /* - * 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. + * Center a rectangle inside another rectangle */ -static void play_sound(int num, SInt16 vol) +static void center_rect(Rect *r, Rect *s) { - OSErr err; - int i; - int prev_num; - SndListHandle h; - SndChannelPtr chan; - SCStatus status; + int centerx = (s->left + s->right)/2; + int centery = (2*s->top + s->bottom)/3; + int dx = centerx - (r->right - r->left)/2 - r->left; + int dy = centery - (r->bottom - r->top)/2 - r->top; + r->left += dx; + r->right += dx; + r->top += dy; + r->bottom += dy; +} - static int next_chan; - static SInt16 channel_occupants[MAX_CHANNELS]; - static SndCommand volume_cmd, quiet_cmd; +#ifdef MACH_O_CARBON - /* Initialise sound channels */ - if (!channel_initialised) - { - for (i = 0; i < MAX_CHANNELS; i++) - { - /* Paranoia - Clear occupant table */ - /* channel_occupants[i] = 0; */ +/* Carbon File Manager utilities by pelpel */ - /* Create sound channel for all sounds to play from */ - err = SndNewChannel(&channels[i], sampledSynth, initMono, 0L); +/* + * (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; - /* Error */ - if (err != noErr) - { - /* Free channels */ - while (--i >= 0) - { - SndDisposeChannel(channels[i], TRUE); - } + /* Convert pathname to FSRef ... */ + err = FSPathMakeRef(path, &ref, NULL); + if (err != noErr) return (err); - /* Notify error */ -#ifdef JP - plog("¥µ¥¦¥ó¥É¥Á¥ã¥ó¥Í¥ë¤ò½é´ü²½½ÐÍè¤Þ¤»¤ó!"); -#else - plog("Cannot initialise sound channels!"); -#endif + /* ... then FSRef to FSSpec */ + err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL); + + /* Inform caller of success or failure */ + return (err); +} - /* Cancel request */ - use_sound = arg_sound = FALSE; - /* Failure */ - return; - } - } +/* + * (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; - /* First channel to use */ - next_chan = 0; + /* Convert FSSpec to FSRef ... */ + err = FSpMakeFSRef(spec, &ref); + if (err != noErr) return (err); - /* Prepare volume command */ - volume_cmd.cmd = volumeCmd; - volume_cmd.param1 = 0; - volume_cmd.param2 = 0; + /* ... then FSRef to pathname */ + err = FSRefMakePath(&ref, buf, size); - /* Prepare quiet command */ - quiet_cmd.cmd = quietCmd; - quiet_cmd.param1 = 0; - quiet_cmd.param2 = 0; + /* Inform caller of success or failure */ + return (err); +} - /* Initialisation complete */ - channel_initialised = TRUE; - } - /* Paranoia */ - if ((num <= 0) || (num >= SOUND_MAX)) return; +/* + * (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; - /* Prepare volume command */ - volume_cmd.param2 = ((SInt32)vol << 16) | vol; + /* Convert pathname to FSSpec */ + if (path_to_spec(pathname, &spec) != noErr) return; - /* Channel to use (round robin) */ - chan = channels[next_chan]; + /* Obtain current finder info of the file */ + if (FSpGetFInfo(&spec, &info) != noErr) return; - /* See if the resource is already in use */ - if (sample_refs[num] > 0) - { - /* Resource in use */ - h = samples[num]; + /* Overwrite creator and type */ + info.fdCreator = fcreator; + info.fdType = ftype; + err = FSpSetFInfo(&spec, &info); - /* Increase the refcount */ - sample_refs[num]++; - } + /* Done */ + return; +} - /* 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; +#else /* MACH_O_CARBON */ -#ifndef USE_QT_SOUND - /* Load resource */ - LoadResource((Handle)h); +/* + * Convert a pascal string in place + * + * This function may be defined elsewhere, but since it is so + * small, it is not worth finding the proper function name for + * all the different platforms. + */ +static void ptocstr(StringPtr src) +{ + int i; - /* Remember it */ - samples[num] = h; + /* Hack -- pointer */ + char *s = (char*)(src); -#endif /* !USE_QT_SOUND */ + /* Hack -- convert the string */ + for (i = s[0]; i; i--, s++) s[0] = s[1]; - /* Lock the handle */ - HLockHi((Handle)h); + /* Hack -- terminate the string */ + s[0] = '\0'; +} - /* Initialise refcount */ - sample_refs[num] = 1; - } - /* Poll the channel */ - err = SndChannelStatus(chan, sizeof(SCStatus), &status); +#if defined(USE_SFL_CODE) - /* 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]; +/* + * The following three routines (pstrcat, pstrinsert, and PathNameFromDirID) + * were taken from the Think Reference section called "Getting a Full Pathname" + * (under the File Manager section). We need PathNameFromDirID to get the + * full pathname of the opened savefile, making no assumptions about where it + * is. + * + * I had to hack PathNameFromDirID a little for MetroWerks, but it's awfully + * nice. + */ +static void pstrcat(StringPtr dst, StringPtr src) +{ + /* copy string in */ + BlockMove(src + 1, dst + *dst + 1, *src); - /* Process previously played sound */ - if (prev_num != 0) - { - /* Decrease refcount */ - sample_refs[prev_num]--; + /* adjust length byte */ + *dst += *src; +} - /* We can free it now */ - if (sample_refs[prev_num] <= 0) - { - /* Unlock */ - HUnlock((Handle)samples[prev_num]); +/* + * pstrinsert - insert string 'src' at beginning of string 'dst' + */ +static void pstrinsert(StringPtr dst, StringPtr src) +{ + /* make room for new string */ + BlockMove(dst + 1, dst + *src + 1, *dst); -#ifndef USE_QT_SOUND + /* copy new string in */ + BlockMove(src + 1, dst + 1, *src); - /* Release */ - ReleaseResource((Handle)samples[prev_num]); + /* adjust length byte */ + *dst += *src; +} - /* Forget handle */ - samples[prev_num] = NULL; +static void PathNameFromDirID(long dirID, short vRefNum, StringPtr fullPathName) +{ + CInfoPBRec block; + Str255 directoryName; + OSErr err; -#endif /* !USE_QT_SOUND */ + fullPathName[0] = '\0'; - /* Paranoia */ - sample_refs[prev_num] = 0; - } + block.dirInfo.ioDrParID = dirID; + block.dirInfo.ioNamePtr = directoryName; + + while (1) + { + block.dirInfo.ioVRefNum = vRefNum; + block.dirInfo.ioFDirIndex = -1; + block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID; + err = PBGetCatInfo(&block, FALSE); + pstrcat(directoryName, (StringPtr)"\p:"); + pstrinsert(fullPathName, directoryName); + if (block.dirInfo.ioDrDirID == 2) break; } +} - /* Remember this sound as the current occupant of the channel */ - channel_occupants[next_chan] = num; +#endif +#endif /* MACH_O_CARBON */ - /* Set up volume for channel */ - SndDoImmediate(chan, &volume_cmd); - - /* Play new sound asynchronously */ - SndPlay(chan, h, TRUE); +/* + * Activate a given window, if necessary + */ +static void activate(WindowPtr w) +{ + /* Activate */ + if (active != w) + { + /* Activate */ +#if TARGET_API_MAC_CARBON + if (w) SetPortWindowPort(w); +#else + if (w) SetPort(w); +#endif - /* Schedule next channel (round robin) */ - next_chan++; - if (next_chan >= MAX_CHANNELS) next_chan = 0; + /* Remember */ + active = w; + } } -# else /* USE_ASYNC_SOUND */ /* - * Play sound synchronously - * - * This may not be your choice, but much safer and much less resource hungry. + * Display a warning message */ -static void play_sound(int num, SInt16 vol) +static void mac_warning(cptr warning) { - Handle handle; - Str255 sound; + Str255 text; + int len, i; - /* Get the proper sound name */ - strnfmt((char*)sound + 1, 255, "%.16s.wav", angband_sound_name[num]); - sound[0] = strlen((char*)sound + 1); + /* Limit of 250 chars */ + len = strlen(warning); + if (len > 250) len = 250; - /* Obtain resource XXX XXX XXX */ - handle = GetNamedResource('snd ', sound); + /* Make a "Pascal" string */ + text[0] = len; + for (i=0; ilast = a; +} + +#endif /* ANGBAND_LITE_MAC */ /* - * 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 + * Hack -- Apply and Verify the "font" info + * + * This should usually be followed by "term_data_check_size()" */ -#if TARGET_API_MAC_CARBON -static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname) +static void term_data_check_font(term_data *td) { - CInfoPBRec pb; - int err; - int i, j; + int i; - char res[1000]; - - FSSpec spec; - short vref; - long dirID; - - i=999; + FontInfo info; - res[i]=0; i--; - for (j=1; j<=fname[0]; j++) + WindowPtr old = active; + + + /* Activate */ + activate(td->w); + + /* Instantiate font */ + TextFont(td->font_id); + TextSize(td->font_size); + TextFace(td->font_face); + + /* Extract the font info */ + GetFontInfo(&info); + + /* Assume monospaced */ + td->font_mono = TRUE; + + /* Extract the font sizing values XXX XXX XXX */ + td->font_wid = CharWidth('@'); /* info.widMax; */ + td->font_hgt = info.ascent + info.descent; + td->font_o_x = 0; + td->font_o_y = info.ascent; + + /* Check important characters */ + for (i = 33; i < 127; i++) { - res[i-fname[0]+j] = fname[j]; + /* Hack -- notice non-mono-space */ + if (td->font_wid != CharWidth(i)) td->font_mono = FALSE; + + /* Hack -- collect largest width */ + if (td->font_wid < CharWidth(i)) td->font_wid = CharWidth(i); } - i-=fname[0]; - vref = vrefnum; - dirID = refnum; + /* Set default offsets */ + td->tile_o_x = td->font_o_x; + td->tile_o_y = td->font_o_y; - while (1) - { - pb.dirInfo.ioDrDirID=pb.dirInfo.ioDrParID; - err = FSMakeFSSpec( vref, dirID, "\p", &spec ); - - if( err != noErr ) - break; - - res[i] = ':'; i--; - for (j=1; j<=spec.name[0]; j++) - { - res[i-spec.name[0]+j] = spec.name[j]; - } - i -= spec.name[0]; - - dirID = spec.parID; + /* Set default tile size */ + if( td->tile_wid == 0 && td->tile_hgt == 0 ){ + td->tile_wid = td->font_wid; + td->tile_hgt = td->font_hgt; } - /* Extract the result */ - for (j = 0, i++; res[i]; j++, i++) buf[j] = res[i]; - buf[j] = 0; + /* Re-activate the old window */ + activate(old); } -#else -static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname) -{ - DirInfo pb; - Str255 name; - int err; - int i, j; - char res[1000]; - i=999; +/* + * Hack -- Apply and Verify the "size" info + */ +static void term_data_check_size(term_data *td) +{ + BitMap screen; + +#if TARGET_API_MAC_CARBON + GetQDGlobalsScreenBits( &screen ); +#else + screen = qd.screenBits; +#endif + /* Minimal window size */ + if (td == &data[0]) + { + /* Enforce minimal size */ + if (td->cols < 80) td->cols = 80; + if (td->rows < 24) td->rows = 24; + } - res[i]=0; i--; - for (j=1; j<=fname[0]; j++) + /* Allow small windows for the rest */ + else { - res[i-fname[0]+j] = fname[j]; + if (td->cols < 1) td->cols = 1; + if (td->rows < 1) td->rows = 1; } - i-=fname[0]; - pb.ioCompletion=NULL; - pb.ioNamePtr=name; - pb.ioVRefNum=vrefnum; - pb.ioDrParID=refnum; - pb.ioFDirIndex=-1; + /* Minimal tile size */ + if (td->tile_wid < 4) td->tile_wid = 4; + if (td->tile_hgt < 4) td->tile_hgt = 4; - while (1) - { - pb.ioDrDirID=pb.ioDrParID; - err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE); - res[i] = ':'; i--; - for (j=1; j<=name[0]; j++) - { - res[i-name[0]+j] = name[j]; - } - i -= name[0]; + /* Default tile offsets */ + td->tile_o_x = (td->tile_wid - td->font_wid) / 2; + td->tile_o_y = (td->tile_hgt - td->font_hgt) / 2; - if (pb.ioDrDirID == fsRtDirID) break; + /* Minimal tile offsets */ + if (td->tile_o_x < 0) td->tile_o_x = 0; + if (td->tile_o_y < 0) td->tile_o_y = 0; + + /* Apply font offsets */ + td->tile_o_x += td->font_o_x; + td->tile_o_y += td->font_o_y; + + /* Calculate full window size */ + td->size_wid = td->cols * td->tile_wid + td->size_ow1 + td->size_ow2; + td->size_hgt = td->rows * td->tile_hgt + td->size_oh1 + td->size_oh2; + + /* Verify the top */ + if (td->r.top > screen.bounds.bottom - td->size_hgt) + { + td->r.top = screen.bounds.bottom - td->size_hgt; } - /* Extract the result */ - for (j = 0, i++; res[i]; j++, i++) buf[j] = res[i]; - buf[j] = 0; -} -#endif + /* Verify the top */ + if (td->r.top < screen.bounds.top + 30) + { + td->r.top = screen.bounds.top + 30; + } -#if TARGET_API_MAC_CARBON -pascal OSErr FSpLocationFromFullPath(short fullPathLength, - const void *fullPath, - FSSpec *spec) -{ - AliasHandle alias; - OSErr result; - Boolean wasChanged; - Str32 nullString; - - /* Create a minimal alias from the full pathname */ - nullString[0] = 0; /* null string to indicate no zone or server name */ - result = NewAliasMinimalFromFullPath(fullPathLength, fullPath, nullString, nullString, &alias); - if ( result == noErr ) + /* Verify the left */ + if (td->r.left > screen.bounds.right - td->size_wid) { - /* Let the Alias Manager resolve the alias. */ - result = ResolveAlias(NULL, alias, spec, &wasChanged); - - /* work around Alias Mgr sloppy volume matching bug */ - if ( spec->vRefNum == 0 ) - { - /* invalidate wrong FSSpec */ - spec->parID = 0; - spec->name[0] = 0; - result = nsvErr; - } - DisposeHandle((Handle)alias); /* Free up memory used */ + td->r.left = screen.bounds.right - td->size_wid; } - return ( result ); -} -#endif -#if 0 + /* Verify the left */ + if (td->r.left < screen.bounds.left) + { + td->r.left = screen.bounds.left; + } -/* - * XXX XXX XXX Allow the system to ask us for a filename - */ -static bool askfor_file(char *buf, int len) -{ - SFReply reply; - Str255 dflt; - Point topleft; - short vrefnum; - long drefnum, junk; + /* Calculate bottom right corner */ + td->r.right = td->r.left + td->size_wid; + td->r.bottom = td->r.top + td->size_hgt; - /* Default file name */ - sprintf((char*)dflt + 1, "%s's description", buf); - dflt[0] = strlen((char*)dflt + 1); + /* Assume no graphics */ + td->t->higher_pict = FALSE; + td->t->always_pict = FALSE; - /* Ask for a file name */ - topleft.h=(qd.screenBits.bounds.left+qd.screenBits.bounds.right)/2-344/2; - topleft.v=(2*qd.screenBits.bounds.top+qd.screenBits.bounds.bottom)/3-188/2; - SFPutFile(topleft, "\pSelect a filename:", dflt, NULL, &reply); - /* StandardPutFile("\pSelect a filename:", dflt, &reply); */ +#ifdef ANGBAND_LITE_MAC - /* Process */ - if (reply.good) - { - int fc; + /* No graphics */ - /* Get info */ - GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk); +#else /* ANGBAND_LITE_MAC */ - /* Extract the name */ - refnum_to_name(buf, drefnum, vrefnum, (char*)reply.fName); + /* Handle graphics */ + if (use_graphics) + { + /* Use higher_pict whenever possible */ + if (td->font_mono) td->t->higher_pict = TRUE; - /* Success */ - return (TRUE); + /* Use always_pict only when necessary */ + else td->t->always_pict = TRUE; } - /* Failure */ - return (FALSE); -} - -#endif +#endif /* ANGBAND_LITE_MAC */ -#if !TARGET_API_MAC_CARBON -static void local_to_global( Rect *r ) -{ - Point temp; - - temp.h = r->left; - temp.v = r->top; - - LocalToGlobal( &temp ); - - r->left = temp.h; - r->top = temp.v; - - temp.h = r->right; - temp.v = r->bottom; - - LocalToGlobal( &temp ); - - r->right = temp.h; - r->bottom = temp.v; + /* Fake mono-space */ + if (!td->font_mono || + (td->font_wid != td->tile_wid) || + (td->font_hgt != td->tile_hgt)) + { + /* Handle fake monospace -- this is SLOW */ + if (td->t->higher_pict) td->t->higher_pict = FALSE; + td->t->always_pict = TRUE; + } } -#endif /* !TARGET_API_MAC_CARBON */ -static void global_to_local( Rect *r ) +/* + * Hack -- resize a term_data + * + * This should normally be followed by "term_data_resize()" + */ +static void term_data_resize(term_data *td) { - Point temp; - - temp.h = r->left; - temp.v = r->top; - - GlobalToLocal( &temp ); - - r->left = temp.h; - r->top = temp.v; - - temp.h = r->right; - temp.v = r->bottom; - - GlobalToLocal( &temp ); - - r->right = temp.h; - r->bottom = temp.v; + /* Actually resize the window */ + SizeWindow(td->w, td->size_wid, td->size_hgt, 0); } -#ifdef MAC_MPW /* - * Convert pathname to an appropriate format, because MPW's - * CarbonStdCLib chose to use system's native path format, - * making our lives harder to create binaries that run on - * OS 8/9 and OS X :( -- pelpel + * Hack -- redraw a term_data + * + * Note that "Term_redraw()" calls "TERM_XTRA_CLEAR" */ -void convert_pathname(char* path) +static void term_data_redraw(term_data *td) { - char buf[1024]; + term *old = Term; - /* Nothing has to be done for CarbonLib on Classic */ - if (mac_os_version >= 0x1000) - { - /* Convert to POSIX style */ - ConvertHFSPathToUnixPath(path, buf); + /* Activate the term */ + Term_activate(td->t); - /* Copy the result back */ - strcpy(path, buf); - } + /* Redraw the contents */ + Term_redraw(); - /* Done. */ - return; -} + /* Flush the output */ + Term_fresh(); -# ifdef CHECK_MODIFICATION_TIME + /* Restore the old term */ + Term_activate(old); + + /* No need to redraw */ +#if TARGET_API_MAC_CARBON + { + RgnHandle theRgn = NewRgn(); + GetWindowRegion( td->w, kWindowContentRgn, theRgn ); + ValidWindowRgn( (WindowRef)(td->w), theRgn ); + DisposeRgn( theRgn ); + } +#else + ValidRect(&td->w->portRect); +#endif -/* - * Although there is no easy way to emulate fstat in the old interface, - * we still can do stat-like things, because Mac OS is an OS. - */ -static int get_modification_time(cptr path, u32b *mod_time) -{ - CInfoPBRec pb; - Str255 pathname; - int i; +} - /* Paranoia - make sure the pathname fits in Str255 */ - i = strlen(path); - if (i > 255) return (-1); - /* Convert pathname to a Pascal string */ - strncpy((char *)pathname + 1, path, 255); - pathname[0] = i; - /* Set up parameter block */ - pb.hFileInfo.ioNamePtr = pathname; - pb.hFileInfo.ioFDirIndex = 0; - pb.hFileInfo.ioVRefNum = app_vol; - pb.hFileInfo.ioDirID = 0; - /* Get catalog information of the file */ - if (PBGetCatInfoSync(&pb) != noErr) return (-1); +#ifdef ANGBAND_LITE_MAC - /* Set modification date and time */ - *mod_time = pb.hFileInfo.ioFlMdDat; +/* No graphics */ - /* Success */ - return (0); -} +#else /* ANGBAND_LITE_MAC */ /* - * A (non-Mach-O) Mac OS version of check_modification_time, for those - * compilers without good enough POSIX-compatibility libraries XXX XXX + * Graphics support */ -errr check_modification_date(int fd, cptr template_file) -{ -#pragma unused(fd) - u32b txt_stat, raw_stat; - char *p; - char fname[32]; - char buf[1024]; - - /* Build the file name */ - path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, template_file); - /* XXX XXX XXX */ - convert_pathname(buf); - - /* Obtain modification time */ - if (get_modification_time(buf, &txt_stat)) return (-1); - - /* XXX Build filename of the corresponding *.raw file */ - strnfmt(fname, sizeof(fname), "%s", template_file); +/* + * 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 */ - /* Find last '.' */ - p = strrchr(fname, '.'); +/* + * Width and height of a tile in pixels + */ +static int grafWidth = 0; +static int grafHeight = 0; - /* Can't happen */ - if (p == NULL) return (-1); +/* + * Numbers of rows and columns in tiles, calculated by + * the PICT loading code + */ +static int pictCols = 0; +static int pictRows = 0; - /* Substitute ".raw" for ".txt" */ - strcpy(p, ".raw"); +/* + * 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 - /* Build the file name of the raw file */ - path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, fname); +/* + * Current and requested graphics modes + */ +static int graf_mode = GRAF_MODE_NONE; +static int graf_mode_req = GRAF_MODE_NONE; - /* XXX XXX XXX */ - convert_pathname(buf); - /* Obtain modification time */ - if (get_modification_time(buf, &raw_stat)) return (-1); +/* + * Forward Declare + */ +typedef struct FrameRec FrameRec; - /* Ensure the text file is not newer than the raw file */ - if (txt_stat > raw_stat) return (-1); +/* + * Frame + * + * - GWorld for the frame image + * - Handle to pix map (saved for unlocking/locking) + * - Pointer to color pix map (valid only while locked) + */ +struct FrameRec +{ + GWorldPtr framePort; + PixMapHandle framePixHndl; + PixMapPtr framePix; + +}; - /* Keep using the current .raw file */ - return (0); -} -# endif /* CHECK_MODIFICATION_TIME */ +/* + * The global picture data + */ +static FrameRec *frameP = NULL; -#endif /* MAC_MPW */ /* - * Center a rectangle inside another rectangle + * Lock a frame */ -static void center_rect(Rect *r, Rect *s) +static void BenSWLockFrame(FrameRec *srcFrameP) { - int centerx = (s->left + s->right)/2; - int centery = (2*s->top + s->bottom)/3; - int dx = centerx - (r->right - r->left)/2 - r->left; - int dy = centery - (r->bottom - r->top)/2 - r->top; - r->left += dx; - r->right += dx; - r->top += dy; - r->bottom += dy; -} - + PixMapHandle pixMapH; -#ifdef MACH_O_CARBON + pixMapH = GetGWorldPixMap(srcFrameP->framePort); + (void)LockPixels(pixMapH); + HLockHi((Handle)pixMapH); + srcFrameP->framePixHndl = pixMapH; +#if TARGET_API_MAC_CARBON + srcFrameP->framePix = (PixMapPtr)*(Handle)pixMapH; +#else + srcFrameP->framePix = (PixMapPtr)StripAddress(*(Handle)pixMapH); +#endif + +} -/* Carbon File Manager utilities by pelpel */ /* - * (Carbon) - * Convert a pathname to a corresponding FSSpec. - * Returns noErr on success. + * Unlock a frame */ -static OSErr path_to_spec(const char *path, FSSpec *spec) +static void BenSWUnlockFrame(FrameRec *srcFrameP) { - OSErr err; - FSRef ref; - - /* Convert pathname to FSRef ... */ - err = FSPathMakeRef(path, &ref, NULL); - if (err != noErr) return (err); + if (srcFrameP->framePort != NULL) + { + HUnlock((Handle)srcFrameP->framePixHndl); + UnlockPixels(srcFrameP->framePixHndl); + } - /* ... then FSRef to FSSpec */ - err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL); + srcFrameP->framePix = NULL; - /* Inform caller of success or failure */ - return (err); } +#ifdef MACH_O_CARBON /* - * (Carbon) - * Convert a FSSpec to a corresponding pathname. - * Returns noErr on success. + * 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 OSErr spec_to_path(const FSSpec *spec, char *buf, size_t size) +static Boolean get_resource_spec( + CFStringRef base_name, CFStringRef type_name, FSSpec *spec) { - OSErr err; + CFURLRef res_url; FSRef ref; - /* Convert FSSpec to FSRef ... */ - err = FSpMakeFSRef(spec, &ref); - if (err != noErr) return (err); + /* Find resource (=file) in the current bundle */ + res_url = CFBundleCopyResourceURL( + CFBundleGetMainBundle(), base_name, type_name, NULL); - /* ... then FSRef to pathname */ - err = FSRefMakePath(&ref, buf, size); + /* Oops */ + if (res_url == NULL) return (false); - /* Inform caller of success or failure */ - return (err); + /* 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); } /* - * (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. + * (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. */ -void fsetfileinfo(cptr pathname, OSType fcreator, OSType ftype) +static OSErr create_gworld_from_spec( + GWorldPtr *tile_gw, FSSpec *tile_spec) { OSErr err; - FSSpec spec; - FInfo info; + GraphicsImportComponent gi; + GWorldPtr gw, tmp_gw; + GDHandle gdh, tmp_gdh; + Rect r; + SInt16 depth; - /* Convert pathname to FSSpec */ - if (path_to_spec(pathname, &spec) != noErr) return; + /* See if QuickTime understands the file format */ + err = GetGraphicsImporterForFile(tile_spec, &gi); - /* Obtain current finder info of the file */ - if (FSpGetFInfo(&spec, &info) != noErr) return; + /* Oops */ + if (err != noErr) return (err); - /* Overwrite creator and type */ - info.fdCreator = fcreator; - info.fdType = ftype; - err = FSpSetFInfo(&spec, &info); + /* Get depth */ + depth = data[0].pixelDepth; - /* Done */ - return; -} + /* Get GDH */ + gdh = data[0].theGDH; + /* Retrieve the rect of the image */ + err = GraphicsImportGetNaturalBounds(gi, &r); -#else /* MACH_O_CARBON */ + /* 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; -/* - * Convert a pascal string in place - * - * This function may be defined elsewhere, but since it is so - * small, it is not worth finding the proper function name for - * all the different platforms. - */ -static void ptocstr(StringPtr src) -{ - int i; + /* Create a GWorld */ + err = NewGWorld(&gw, depth, &r, NULL, gdh, noNewDevice); - /* Hack -- pointer */ - char *s = (char*)(src); + /* Oops */ + if (err != noErr) return (err); - /* Hack -- convert the string */ - for (i = s[0]; i; i--, s++) s[0] = s[1]; + /* Save the pointer to the GWorld */ + *tile_gw = gw; - /* Hack -- terminate the string */ - s[0] = '\0'; -} + /* Save the current GWorld */ + GetGWorld(&tmp_gw, &tmp_gdh); + /* Activate the newly created GWorld */ + (void)GraphicsImportSetGWorld(gi, gw, NULL); -#if defined(USE_SFL_CODE) + /* Prevent pixmap from moving while drawing */ + (void)LockPixels(GetGWorldPixMap(gw)); + /* Clear the pixels */ + EraseRect(&r); -/* - * The following three routines (pstrcat, pstrinsert, and PathNameFromDirID) - * were taken from the Think Reference section called "Getting a Full Pathname" - * (under the File Manager section). We need PathNameFromDirID to get the - * full pathname of the opened savefile, making no assumptions about where it - * is. - * - * I had to hack PathNameFromDirID a little for MetroWerks, but it's awfully - * nice. - */ -static void pstrcat(StringPtr dst, StringPtr src) -{ - /* copy string in */ - BlockMove(src + 1, dst + *dst + 1, *src); + /* Draw the image into it */ + (void)GraphicsImportDraw(gi); - /* adjust length byte */ - *dst += *src; -} + /* Release the lock*/ + UnlockPixels(GetGWorldPixMap(gw)); -/* - * pstrinsert - insert string 'src' at beginning of string 'dst' - */ -static void pstrinsert(StringPtr dst, StringPtr src) -{ - /* make room for new string */ - BlockMove(dst + 1, dst + *src + 1, *dst); + /* Restore GWorld */ + SetGWorld(tmp_gw, tmp_gdh); - /* copy new string in */ - BlockMove(src + 1, dst + 1, *src); + /* Close the image importer */ + CloseComponent(gi); - /* adjust length byte */ - *dst += *src; + /* Success */ + return (noErr); } -static void PathNameFromDirID(long dirID, short vRefNum, StringPtr fullPathName) +#else /* MACH_O_CARBON */ + +static OSErr BenSWCreateGWorldFromPict( + GWorldPtr *pictGWorld, + PicHandle pictH) { - CInfoPBRec block; - Str255 directoryName; - OSErr err; + OSErr err; + GWorldPtr saveGWorld; + GDHandle saveGDevice; + GWorldPtr tempGWorld; + Rect pictRect; + short depth; + GDHandle theGDH; - fullPathName[0] = '\0'; + /* Reset */ + *pictGWorld = NULL; - block.dirInfo.ioDrParID = dirID; - block.dirInfo.ioNamePtr = directoryName; + /* Get depth */ + depth = data[0].pixelDepth; - while (1) + /* Get GDH */ + theGDH = data[0].theGDH; + + /* Obtain size rectangle */ + pictRect = (**pictH).picFrame; + OffsetRect(&pictRect, -pictRect.left, -pictRect.top); + + /* Create a GWorld */ + err = NewGWorld(&tempGWorld, depth, &pictRect, nil, + theGDH, noNewDevice); + + /* Success */ + if (err != noErr) { - block.dirInfo.ioVRefNum = vRefNum; - block.dirInfo.ioFDirIndex = -1; - block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID; - err = PBGetCatInfo(&block, FALSE); - pstrcat(directoryName, (StringPtr)"\p:"); - pstrinsert(fullPathName, directoryName); - if (block.dirInfo.ioDrDirID == 2) break; + return (err); } + + /* Save pointer */ + *pictGWorld = tempGWorld; + + /* Save GWorld */ + GetGWorld(&saveGWorld, &saveGDevice); + + /* Activate */ + SetGWorld(tempGWorld, nil); + + /* Dump the pict into the GWorld */ + (void)LockPixels(GetGWorldPixMap(tempGWorld)); + EraseRect(&pictRect); + DrawPicture(pictH, &pictRect); + UnlockPixels(GetGWorldPixMap(tempGWorld)); + + /* Restore GWorld */ + SetGWorld(saveGWorld, saveGDevice); + + /* Success */ + return (0); } -#endif #endif /* MACH_O_CARBON */ + /* - * Activate a given window, if necessary + * Init the global "frameP" */ -static void activate(WindowPtr w) + +static errr globe_init(void) { - /* Activate */ - if (active != w) - { - /* Activate */ + OSErr err; + + 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 - if (w) SetPortWindowPort(w); + SetPortWindowPort(data[0].w); #else - if (w) SetPort(w); + SetPort(data[0].w); #endif - /* Remember */ - active = w; - } -} +#ifdef MACH_O_CARBON -/* - * Display a warning message - */ -static void mac_warning(cptr warning) -{ - Str255 text; - int len, i; + /* 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; - /* Limit of 250 chars */ - len = strlen(warning); - if (len > 250) len = 250; + /* Lock it */ + BenSWLockFrame(frameP); - /* Make a "Pascal" string */ - text[0] = len; - for (i=0; iframePort = tempPictGWorldP; -#ifdef ANGBAND_LITE_MAC + /* Lock it */ + BenSWLockFrame(frameP); + } + } + } +#endif /* MACH_O_CARBON */ -/* - * Hack -- activate a color (0 to 255) - */ -#define term_data_color(TD,A) /* Nothing */ -#else /* ANGBAND_LITE_MAC */ + /* Result */ + return (err); +} + /* - * Hack -- activate a color (0 to 255) + * Nuke the global "frameP" */ -static void term_data_color(term_data *td, int a) +static errr globe_nuke(void) { - u16b rv, gv, bv; + /* Dispose */ + if (frameP) + { + /* Unlock */ + BenSWUnlockFrame(frameP); - RGBColor color; + /* Dispose of the GWorld */ + DisposeGWorld(frameP->framePort); - /* Extract the R,G,B data */ - rv = angband_color_table[a][1]; - gv = angband_color_table[a][2]; - bv = angband_color_table[a][3]; + /* Dispose of the memory */ + DisposePtr((Ptr)frameP); - /* Set the color */ - color.red = (rv | (rv << 8)); - color.green = (gv | (gv << 8)); - color.blue = (bv | (bv << 8)); + /* Forget */ + frameP = NULL; + } - /* Activate the color */ - RGBForeColor(&color); + /* Flush events */ + FlushEvents(everyEvent, 0); - /* Memorize color */ - td->last = a; + /* Success */ + return (0); } -#endif /* ANGBAND_LITE_MAC */ +# ifdef USE_ASYNC_SOUND /* - * Hack -- Apply and Verify the "font" info - * - * This should usually be followed by "term_data_check_size()" + * Asynchronous sound player revised */ -static void term_data_check_font(term_data *td) -{ - int i; - - FontInfo info; - - WindowPtr old = active; - +#if defined(USE_QT_SOUND) && !defined(MACH_O_CARBON) +# undef USE_QT_SOUND +#endif /* USE_QT_SOUND && !MACH_O_CARBON */ - /* Activate */ - activate(td->w); - /* Instantiate font */ - TextFont(td->font_id); - TextSize(td->font_size); - TextFace(td->font_face); +/* + * Number of channels in the channel pool + */ +#if TARGET_API_MAC_CARBON +#define MAX_CHANNELS 8 +#else +#define MAX_CHANNELS 4 +#endif - /* Extract the font info */ - GetFontInfo(&info); +/* + * A pool of sound channels + */ +static SndChannelPtr channels[MAX_CHANNELS]; - /* Assume monospaced */ - td->font_mono = TRUE; +/* + * Status of the channel pool + */ +static Boolean channel_initialised = FALSE; - /* Extract the font sizing values XXX XXX XXX */ - td->font_wid = CharWidth('@'); /* info.widMax; */ - td->font_hgt = info.ascent + info.descent; - td->font_o_x = 0; - td->font_o_y = info.ascent; +/* + * Data handles containing sound samples + */ +static SndListHandle samples[SOUND_MAX]; - /* Check important characters */ - for (i = 33; i < 127; i++) - { - /* Hack -- notice non-mono-space */ - if (td->font_wid != CharWidth(i)) td->font_mono = FALSE; +/* + * Reference counts of sound samples + */ +static SInt16 sample_refs[SOUND_MAX]; - /* Hack -- collect largest width */ - if (td->font_wid < CharWidth(i)) td->font_wid = CharWidth(i); - } - /* Set default offsets */ - td->tile_o_x = td->font_o_x; - td->tile_o_y = td->font_o_y; +/* + * 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 % */ - /* Set default tile size */ - if( td->tile_wid == 0 && td->tile_hgt == 0 ){ - td->tile_wid = td->font_wid; - td->tile_hgt = td->font_hgt; - } +/* I'm just too lazy to write a panel for this XXX XXX */ +static SInt16 sound_volume = SOUND_VOLUME_MAX; - /* Re-activate the old window */ - activate(old); -} +#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 + */ /* - * Hack -- Apply and Verify the "size" info + * (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 term_data_check_size(term_data *td) +static void load_sounds(void) { - BitMap screen; - -#if TARGET_API_MAC_CARBON - GetQDGlobalsScreenBits( &screen ); -#else - screen = qd.screenBits; -#endif - /* Minimal window size */ - if (td == &data[0]) - { - /* Enforce minimal size */ - if (td->cols < 80) td->cols = 80; - if (td->rows < 24) td->rows = 24; - } + OSErr err; + int i; - /* Allow small windows for the rest */ - else + /* 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++) { - if (td->cols < 1) td->cols = 1; - if (td->rows < 1) td->rows = 1; - } + /* 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; - /* Minimal tile size */ - if (td->tile_wid < 4) td->tile_wid = 4; - if (td->tile_hgt < 4) td->tile_hgt = 4; + /* Allocate CFString with the name of sound event to be processed */ + name = CFStringCreateWithCString(NULL, angband_sound_name[i], + kTextEncodingUS_ASCII); - /* Default tile offsets */ - td->tile_o_x = (td->tile_wid - td->font_wid) / 2; - td->tile_o_y = (td->tile_hgt - td->font_hgt) / 2; + /* Error */ + if (name == NULL) continue; - /* Minimal tile offsets */ - if (td->tile_o_x < 0) td->tile_o_x = 0; - if (td->tile_o_y < 0) td->tile_o_y = 0; + /* Find sound sample resource with the same name */ + res = get_resource_spec(name, CFSTR("wav"), &spec); - /* Apply font offsets */ - td->tile_o_x += td->font_o_x; - td->tile_o_y += td->font_o_y; + /* Free the reference to CFString */ + CFRelease(name); - /* Calculate full window size */ - td->size_wid = td->cols * td->tile_wid + td->size_ow1 + td->size_ow2; - td->size_hgt = td->rows * td->tile_hgt + td->size_oh1 + td->size_oh2; + /* Error */ + if (!res) continue; - /* Verify the top */ - if (td->r.top > screen.bounds.bottom - td->size_hgt) - { - td->r.top = screen.bounds.bottom - td->size_hgt; - } + /* Open the sound file */ + err = OpenMovieFile(&spec, &file_id, fsRdPerm); - /* Verify the top */ - if (td->r.top < screen.bounds.top + 30) - { - td->r.top = screen.bounds.top + 30; - } + /* Error */ + if (err != noErr) continue; - /* Verify the left */ - if (td->r.left > screen.bounds.right - td->size_wid) - { - td->r.left = screen.bounds.right - td->size_wid; - } + /* Create Movie from the file */ + err = NewMovieFromFile(&movie, file_id, &res_id, movie_name, + newMovieActive, NULL); - /* Verify the left */ - if (td->r.left < screen.bounds.left) - { - td->r.left = screen.bounds.left; - } + /* Error */ + if (err != noErr) goto close_file; - /* Calculate bottom right corner */ - td->r.right = td->r.left + td->size_wid; - td->r.bottom = td->r.top + td->size_hgt; + /* Get the first track of the movie */ + track = GetMovieIndTrackType(movie, 1, AudioMediaCharacteristic, + movieTrackCharacteristic | movieTrackEnabledOnly ); - /* Assume no graphics */ - td->t->higher_pict = FALSE; - td->t->always_pict = FALSE; + /* Error */ + if (track == NULL) goto close_movie; -#ifdef ANGBAND_LITE_MAC + /* Allocate a handle to store sample */ + h = NewHandle(0); - /* No graphics */ + /* Error */ + if (h == NULL) goto close_track; -#else /* ANGBAND_LITE_MAC */ + /* Dump the sample into the handle */ + err = PutMovieIntoTypedHandle(movie, track, soundListRsrc, h, 0, + GetTrackDuration(track), 0L, NULL); - /* Handle graphics */ - if (use_graphics) - { - /* Use higher_pict whenever possible */ - if (td->font_mono) td->t->higher_pict = TRUE; + /* Success */ + if (err == noErr) + { + /* Store the handle in the sample list */ + samples[i] = (SndListHandle)h; + } - /* Use always_pict only when necessary */ - else td->t->always_pict = TRUE; - } + /* Failure */ + else + { + /* Free unused handle */ + DisposeHandle(h); + } -#endif /* ANGBAND_LITE_MAC */ + /* Free the track */ + close_track: DisposeMovieTrack(track); - /* Fake mono-space */ - if (!td->font_mono || - (td->font_wid != td->tile_wid) || - (td->font_hgt != td->tile_hgt)) - { - /* Handle fake monospace -- this is SLOW */ - if (td->t->higher_pict) td->t->higher_pict = FALSE; - td->t->always_pict = TRUE; + /* Free the movie */ + close_movie: DisposeMovie(movie); + + /* Close the movie file */ + close_file: CloseMovieFile(file_id); } + + /* Stop QuickTime */ + ExitMovies(); } +#else /* USE_QT_SOUND */ + /* - * Hack -- resize a term_data + * Return a handle of 'snd ' resource given Angband sound event number, + * or NULL if it isn't found. * - * This should normally be followed by "term_data_resize()" + * Globals referenced: angband_sound_name[] (variable.c) */ -static void term_data_resize(term_data *td) +static SndListHandle find_sound(int num) { - /* Actually resize the window */ - SizeWindow(td->w, td->size_wid, td->size_hgt, 0); + 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 */ /* - * Hack -- redraw a term_data + * Clean up sound support - to be called when the game exits. * - * Note that "Term_redraw()" calls "TERM_XTRA_CLEAR" + * Globals referenced: channels[], samples[], sample_refs[]. */ -static void term_data_redraw(term_data *td) +static void cleanup_sound(void) { - term *old = Term; - - /* Activate the term */ - Term_activate(td->t); - - /* Redraw the contents */ - Term_redraw(); + int i; - /* Flush the output */ - Term_fresh(); + /* No need to clean it up */ + if (!channel_initialised) return; - /* Restore the old term */ - Term_activate(old); - - /* No need to redraw */ -#if TARGET_API_MAC_CARBON + /* Dispose channels */ + for (i = 0; i < MAX_CHANNELS; i++) { - RgnHandle theRgn = NewRgn(); - GetWindowRegion( td->w, kWindowContentRgn, theRgn ); - ValidWindowRgn( (WindowRef)(td->w), theRgn ); - DisposeRgn( theRgn ); + /* Drain sound commands and free the channel */ + SndDisposeChannel(channels[i], TRUE); } -#else - ValidRect(&td->w->portRect); -#endif -} + /* 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 */ + } +} -#ifdef ANGBAND_LITE_MAC -/* No graphics */ +/* + * 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; -#else /* ANGBAND_LITE_MAC */ + static int next_chan; + static SInt16 channel_occupants[MAX_CHANNELS]; + static SndCommand volume_cmd, quiet_cmd; -/* - * Constants - */ + /* 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); -static int pictID = 1001; /* 8x8 tiles; 16x16 tiles are 1002 */ + /* Error */ + if (err != noErr) + { + /* Free channels */ + while (--i >= 0) + { + SndDisposeChannel(channels[i], TRUE); + } -static int grafWidth = 8; /* Always equal to grafHeight */ -static int grafHeight = 8; /* Either 8 or 16 */ + /* Notify error */ +#ifdef JP + plog("¥µ¥¦¥ó¥É¥Á¥ã¥ó¥Í¥ë¤ò½é´ü²½½ÐÍè¤Þ¤»¤ó!"); +#else + plog("Cannot initialise sound channels!"); +#endif -static bool arg_newstyle_graphics; -static bool use_newstyle_graphics; + /* Cancel request */ + use_sound = arg_sound = FALSE; -/* - * Forward Declare - */ -typedef struct FrameRec FrameRec; + /* Failure */ + return; + } + } -/* - * Frame - * - * - GWorld for the frame image - * - Handle to pix map (saved for unlocking/locking) - * - Pointer to color pix map (valid only while locked) - */ -struct FrameRec -{ - GWorldPtr framePort; - PixMapHandle framePixHndl; - PixMapPtr framePix; - -}; + /* First channel to use */ + next_chan = 0; + /* Prepare volume command */ + volume_cmd.cmd = volumeCmd; + volume_cmd.param1 = 0; + volume_cmd.param2 = 0; -/* - * The global picture data - */ -static FrameRec *frameP = NULL; + /* Prepare quiet command */ + quiet_cmd.cmd = quietCmd; + quiet_cmd.param1 = 0; + quiet_cmd.param2 = 0; + /* Initialisation complete */ + channel_initialised = TRUE; + } -/* - * Lock a frame - */ -static void BenSWLockFrame(FrameRec *srcFrameP) -{ - PixMapHandle pixMapH; + /* Paranoia */ + if ((num <= 0) || (num >= SOUND_MAX)) return; - pixMapH = GetGWorldPixMap(srcFrameP->framePort); - (void)LockPixels(pixMapH); - HLockHi((Handle)pixMapH); - srcFrameP->framePixHndl = pixMapH; -#if TARGET_API_MAC_CARBON - srcFrameP->framePix = (PixMapPtr)*(Handle)pixMapH; -#else - srcFrameP->framePix = (PixMapPtr)StripAddress(*(Handle)pixMapH); -#endif - -} + /* Prepare volume command */ + volume_cmd.param2 = ((SInt32)vol << 16) | vol; + /* Channel to use (round robin) */ + chan = channels[next_chan]; -/* - * Unlock a frame - */ -static void BenSWUnlockFrame(FrameRec *srcFrameP) -{ - if (srcFrameP->framePort != NULL) + /* See if the resource is already in use */ + if (sample_refs[num] > 0) { - HUnlock((Handle)srcFrameP->framePixHndl); - UnlockPixels(srcFrameP->framePixHndl); + /* Resource in use */ + h = samples[num]; + + /* Increase the refcount */ + sample_refs[num]++; } - srcFrameP->framePix = NULL; - -} + /* 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 */ -static OSErr BenSWCreateGWorldFromPict( - GWorldPtr *pictGWorld, - PicHandle pictH) -{ - OSErr err; - GWorldPtr saveGWorld; - GDHandle saveGDevice; - GWorldPtr tempGWorld; - Rect pictRect; - short depth; - GDHandle theGDH; + /* Sample not available */ + if (h == NULL) return; - /* Reset */ - *pictGWorld = NULL; +#ifndef USE_QT_SOUND - /* Get depth */ - depth = data[0].pixelDepth; + /* Load resource */ + LoadResource((Handle)h); - /* Get GDH */ - theGDH = data[0].theGDH; + /* Remember it */ + samples[num] = h; - /* Obtain size rectangle */ - pictRect = (**pictH).picFrame; - OffsetRect(&pictRect, -pictRect.left, -pictRect.top); +#endif /* !USE_QT_SOUND */ - /* Create a GWorld */ - err = NewGWorld(&tempGWorld, depth, &pictRect, nil, - theGDH, noNewDevice); + /* Lock the handle */ + HLockHi((Handle)h); - /* Success */ - if (err != noErr) - { - return (err); + /* Initialise refcount */ + sample_refs[num] = 1; } - /* Save pointer */ - *pictGWorld = tempGWorld; + /* Poll the channel */ + err = SndChannelStatus(chan, sizeof(SCStatus), &status); - /* Save GWorld */ - GetGWorld(&saveGWorld, &saveGDevice); + /* It isn't available */ + if ((err != noErr) || status.scChannelBusy) + { + /* Shut it down */ + SndDoImmediate(chan, &quiet_cmd); + } - /* Activate */ - SetGWorld(tempGWorld, nil); + /* Previously played sound on this channel */ + prev_num = channel_occupants[next_chan]; - /* Dump the pict into the GWorld */ - (void)LockPixels(GetGWorldPixMap(tempGWorld)); - EraseRect(&pictRect); - DrawPicture(pictH, &pictRect); - UnlockPixels(GetGWorldPixMap(tempGWorld)); + /* Process previously played sound */ + if (prev_num != 0) + { + /* Decrease refcount */ + sample_refs[prev_num]--; - /* Restore GWorld */ - SetGWorld(saveGWorld, saveGDevice); - - /* Success */ - return (0); -} + /* 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; -/* - * Init the global "frameP" - */ +#endif /* !USE_QT_SOUND */ -static errr globe_init(void) -{ - OSErr err; - - GWorldPtr tempPictGWorldP; + /* Paranoia */ + sample_refs[prev_num] = 0; + } + } - PicHandle newPictH; + /* Remember this sound as the current occupant of the channel */ + channel_occupants[next_chan] = num; - /* Use window XXX XXX XXX */ -#if TARGET_API_MAC_CARBON - SetPortWindowPort(data[0].w); -#else - SetPort(data[0].w); -#endif + /* Set up volume for channel */ + SndDoImmediate(chan, &volume_cmd); + /* Play new sound asynchronously */ + SndPlay(chan, h, TRUE); - /* Get the pict resource */ - newPictH = GetPicture(pictID); + /* Schedule next channel (round robin) */ + next_chan++; + if (next_chan >= MAX_CHANNELS) next_chan = 0; +} - /* Analyze result */ - err = (newPictH ? 0 : -1); +# else /* USE_ASYNC_SOUND */ - /* Oops */ - if (err == noErr) - { +/* + * 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; - /* Create GWorld */ - err = BenSWCreateGWorldFromPict(&tempPictGWorldP, newPictH); - - /* Release resource */ - ReleaseResource((Handle)newPictH); + /* Get the proper sound name */ + strnfmt((char*)sound + 1, 255, "%.16s.wav", angband_sound_name[num]); + sound[0] = strlen((char*)sound + 1); - /* Error */ - if (err == noErr) - { - /* Create the frame */ - frameP = (FrameRec*)NewPtrClear((Size)sizeof(FrameRec)); + /* Obtain resource XXX XXX XXX */ + handle = GetNamedResource('snd ', sound); - /* Analyze result */ - err = (frameP ? 0 : -1); + /* Oops */ + if (handle == NULL) return; - /* Oops */ - if (err == noErr) - { - /* Save GWorld */ - frameP->framePort = tempPictGWorldP; + /* Load and Lock */ + LoadResource(handle); + HLockHi(handle); - /* Lock it */ - BenSWLockFrame(frameP); - } - } - } + /* Play sound (wait for completion) */ + SndPlay(NULL, (SndListHandle)handle, FALSE); - /* Result */ - return (err); + /* Unlock and release */ + HUnlock(handle); + ReleaseResource(handle); } +# endif /* USE_ASYNC_SOUND */ /* - * Nuke the global "frameP" - */ -static errr globe_nuke(void) -{ - /* Dispose */ - if (frameP) - { - /* Unlock */ - BenSWUnlockFrame(frameP); + Extra Sound Mode +*/ - /* Dispose of the GWorld */ - DisposeGWorld(frameP->framePort); - /* Dispose of the memory */ - DisposePtr((Ptr)frameP); +static short soundmode[8]; - /* Forget */ - frameP = NULL; - } +#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 - /* Flush events */ - FlushEvents(everyEvent, 0); +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, +}; - /* Success */ - return (0); -} +static int ext_sound = 0; +static int ext_graf = 0; +#endif /* !MACH_O_CARBON */ #endif /* ANGBAND_LITE_MAC */ @@ -2290,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); @@ -3153,18 +3336,13 @@ static void cf_save_prefs() /* Gfx settings */ save_pref_short("arg.arg_sound", arg_sound); - save_pref_short("arg.arg_graphics", arg_graphics); - save_pref_short("arg.arg_newstyle_graphics", arg_newstyle_graphics); - save_pref_short("arg.arg_bigtile", arg_bigtile); - -#ifndef MACH_O_CARBON + save_pref_short("arg.graf_mode", graf_mode); + save_pref_short("arg.arg_bigtile", use_bigtile); /* 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++) { @@ -3203,8 +3381,6 @@ static void cf_load_prefs() short pref_major, pref_minor, pref_patch, pref_extra; int i; - MenuHandle m; - /* Assume nothing is wrong, yet */ ok = TRUE; @@ -3228,25 +3404,6 @@ static void cf_load_prefs() return; } -#if 0 - - /* Check version */ - if ((pref_major != PREF_VER_MAJOR) || - (pref_minor != PREF_VER_MINOR) || - (pref_patch != PREF_VER_PATCH) || - (pref_extra != PREF_VER_EXTRA)) - { - /* Message */ - mac_warning( - format("Ignoring %d.%d.%d.%d preferences.", - pref_major, pref_minor, pref_patch, pref_extra)); - - /* Ignore */ - return; - } - -#endif - /* Gfx settings */ { short pref_tmp; @@ -3256,29 +3413,8 @@ static void cf_load_prefs() arg_sound = pref_tmp; /* graphics */ - if (query_load_pref_short("arg.arg_graphics", &pref_tmp)) - arg_graphics = pref_tmp; - - /*newstyle graphics*/ - if (query_load_pref_short("arg.arg_newstyle_graphics", &pref_tmp)) - { - use_newstyle_graphics = pref_tmp; - } - - 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; - } + 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)) @@ -3288,31 +3424,12 @@ static void cf_load_prefs() } -#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 */ - - /* Special menu */ - m = GetMenuHandle(134); - - /* 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); - - /* Item "arg_bigtile"*/ - CheckMenuItem(m, 9, arg_bigtile); - /* Windows */ for (i = 0; i < MAX_TERM_DATA; i++) { @@ -3379,8 +3496,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 */ @@ -3451,25 +3567,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; @@ -3477,21 +3575,6 @@ static void load_prefs(void) for( i = 0 ; i < 7 ; i++ ) soundmode[i] = getshort(); - /* Special menu */ - m = GetMenuHandle(134); - - /* 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); - - /* Item "arg_bigtile"*/ - CheckItem(m, 9, arg_bigtile); - /* Windows */ for (i = 0; i < MAX_TERM_DATA; i++) { @@ -4476,11 +4559,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 } (?) @@ -4488,9 +4566,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; @@ -4500,62 +4639,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; @@ -4623,15 +4755,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)) @@ -4647,15 +4772,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++) @@ -4669,53 +4787,109 @@ static void init_menubar(void) /* Add the item */ AppendMenu(m, buf); - /* Command-Key shortcuts */ - if (i < 8) SetItemCmd(m, i + 1, '0' + i); - } + /* Command-Key shortcuts */ + if (i < 8) SetItemCmd(m, i + 1, '0' + i); + } + + +#if TARGET_API_MAC_CARBON && !defined(MAC_MPW) + + /* CW or gcc -- Use recommended interface for hierarchical menus */ + + /* Special menu (id 134) */ + m = GetMenuHandle(MENU_SPECIAL); + + /* 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); - /* Make the "Special" menu */ - #ifdef JP - m = NewMenu(134, "\pÆÃÊÌ"); - #else - m = NewMenu(134, "\pSpecial"); - #endif - - /* Insert the menu */ - InsertMenu(m, 0); + /* Get graphics (sub)menu (id 144) */ + m = GetMenu(SUBMENU_GRAPH); - /* 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 + /* Insert it as a submenu */ + InsertMenu(m, hierMenu); - /* Make the "TileWidth" menu */ - #ifdef JP - m = NewMenu(135, "\p¥¿¥¤¥ëÉý"); - #else - m = NewMenu(135, "\pTileWidth"); - #endif - /* Insert the menu */ - InsertMenu(m, 0); + /* Get TileWidth (sub)menu (id 145) */ + m = GetMenu(SUBMENU_TILEWIDTH); /* Add some sizes */ for (i = 4; i <= 32; i++) @@ -4731,15 +4905,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++) @@ -4755,6 +4925,10 @@ static void init_menubar(void) } + /* Insert the menu */ + InsertMenu(m, hierMenu); + +#endif /* Update the menu bar */ DrawMenuBar(); } @@ -4788,7 +4962,7 @@ static void setup_menus(void) /* File menu */ - m = GetMenuHandle(129); + m = GetMenuHandle(MENU_FILE); /* Get menu size */ #if TARGET_API_MAC_CARBON @@ -4814,13 +4988,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 } @@ -4828,9 +5002,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 } @@ -4838,9 +5012,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 } @@ -4848,15 +5022,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 @@ -4882,23 +5056,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 @@ -4931,16 +5105,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++) @@ -4957,16 +5131,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++) @@ -4986,7 +5160,7 @@ static void setup_menus(void) /* Size menu */ - m = GetMenuHandle(132); + m = GetMenuHandle(MENU_SIZE); /* Get menu size */ #if TARGET_API_MAC_CARBON @@ -5014,23 +5188,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); @@ -5042,7 +5211,7 @@ static void setup_menus(void) /* Windows menu */ - m = GetMenuHandle(133); + m = GetMenuHandle(MENU_WINDOWS); /* Get menu size */ #if TARGET_API_MAC_CARBON @@ -5064,7 +5233,7 @@ static void setup_menus(void) /* Special menu */ - m = GetMenuHandle(134); + m = GetMenuHandle(MENU_SPECIAL); /* Get menu size */ #if TARGET_API_MAC_CARBON @@ -5079,90 +5248,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); + +#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 "SoundSetting" */ - EnableMenuItem(m, 7); + /* 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); + + /* Item "Sound Config" */ + EnableItem(m, ITEM_SOUND_SETTING); - /* TileWidth menu */ - m = GetMenuHandle(135); + /* 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 */ @@ -5177,44 +5568,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 */ @@ -5228,21 +5602,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 + } @@ -5287,11 +5655,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; @@ -5319,7 +5687,7 @@ static void menu(long mc) break; } #else - if (selection == 1) + if (selection == ITEM_ABOUT) { DialogPtr dialog; Rect r; @@ -5337,41 +5705,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; @@ -5389,7 +5756,7 @@ static void menu(long mc) } /* Save */ - case 5: + case ITEM_SAVE: { if (!can_save){ #ifdef JP @@ -5410,7 +5777,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) @@ -5443,14 +5810,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; @@ -5462,7 +5829,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) @@ -5489,7 +5856,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) @@ -5516,7 +5883,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 */ @@ -5568,7 +5935,7 @@ static void menu(long mc) } /* Size menu */ - case 132: + case MENU_SIZE: { if (!td) break; @@ -5578,7 +5945,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)); @@ -5600,7 +5967,7 @@ static void menu(long mc) } /* Window menu */ - case 133: + case MENU_WINDOWS: { /* Parse */ i = selection - 1; @@ -5630,11 +5997,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; @@ -5645,75 +6033,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; @@ -5723,16 +6084,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; @@ -5742,7 +6108,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)); @@ -5759,8 +6126,8 @@ static void menu(long mc) break; } - /* TileHeight menu */ - case 136: + /* TileHeight submenu */ + case SUBMENU_TILEHEIGHT: { if (!td) break; @@ -5770,7 +6137,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)); @@ -5837,6 +6205,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) @@ -7055,6 +7424,13 @@ int 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";