3 /* Purpose: Simple support for MACINTOSH Angband */
6 * This file should only be compiled with the "Macintosh" version
8 * This file written by "Ben Harrison (benh@phial.com)".
10 * Some code adapted from "MacAngband 2.6.1" by Keith Randall
12 * Maarten Hazewinkel (mmhazewi@cs.ruu.nl) provided some initial
13 * suggestions for the PowerMac port.
15 * Steve Linberg (slinberg@crocker.com) provided the code surrounded
18 * The graphics code is adapted from an extremely minimal subset of
19 * the code from "Sprite World II", an amazing animation package.
21 * See "z-term.c" for info on the concept of the "generic terminal"
23 * The preference file is now a text file named "Angband preferences".
25 * Note that the "preference" file is now a simple text file called
26 * "Angband preferences", which contains the versions information, so
27 * that obsolete preference files can be ignored (this may be bad).
29 * Note that "init1.c", "init2.c", "load1.c", "load2.c", and "birth.c"
30 * should probably be "unloaded" as soon as they are no longer needed,
31 * to save space, but I do not know how to do this.
33 * Stange bug -- The first "ClipRect()" call crashes if the user closes
34 * all the windows, switches to another application, switches back, and
35 * then re-opens the main window, for example, using "command-a".
37 * By default, this file assumes that you will be using a 68020 or better
38 * machine, running System 7 and Color Quickdraw. In fact, the game will
39 * refuse to run unless these features are available. This allows the use
40 * of a variety of interesting features such as graphics and sound.
42 * To create a version which can be used on 68000 machines, or on machines
43 * which are not running System 7 or Color Quickdraw, simply activate the
44 * "ANGBAND_LITE_MAC" compilation flag in the proper header file. This
45 * will disable all "modern" features used in this file, including support
46 * for multiple sub-windows, color, graphics, and sound.
48 * When compiling with the "ANGBAND_LITE_MAC" flag, the "ANGBAND_LITE"
49 * flag will be automatically defined, which will disable many of the
50 * advanced features of the game itself, reducing the total memory usage.
52 * If you are never going to use "graphics" (especially if you are not
53 * compiling support for graphics anyway) then you can delete the "pict"
54 * resource with id "1001" with no dangerous side effects.
59 * Important Resources in the resource file:
61 * FREF 130 = 'A271' / 'APPL' (application)
62 * FREF 129 = 'A271' / 'SAVE' (save file)
63 * FREF 130 = 'A271' / 'TEXT' (bone file, generic text file)
64 * FREF 131 = 'A271' / 'DATA' (binary image file, score file)
66 * DLOG 128 = "About Angband..."
68 * ALRT 128 = unused (?)
69 * ALRT 129 = "Warning..."
70 * ALRT 130 = "Are you sure you want to quit without saving?"
72 * DITL 128 = body for DLOG 128
73 * DITL 129 = body for ALRT 129
74 * DITL 130 = body for ALRT 130
76 * ICON 128 = "warning" icon
78 * MENU 128 = apple (about, -, ...)
79 * MENU 129 = File (new, open, close, save, -, exit, quit)
80 * MENU 130 = Edit (undo, -, cut, copy, paste, clear)
82 * PICT 1001 = Graphics tile set
88 * all 'APEX' files have a filename of the form "*:apex:*" (?)
89 * all 'BONE' files have a filename of the form "*:bone:*" (?)
90 * all 'DATA' files have a filename of the form "*:data:*"
91 * all 'SAVE' files have a filename of the form "*:save:*"
92 * all 'USER' files have a filename of the form "*:user:*" (?)
94 * Perhaps we should attempt to set the "_ftype" flag inside this file,
95 * to avoid nasty file type information being spread all through the
96 * rest of the code. (?) This might require adding hooks into the
97 * "fd_open()" and "my_fopen()" functions in "util.c". XXX XXX XXX
102 * Reasons for each header file:
104 * angband.h = Angband header file
106 * Types.h = (included anyway)
107 * Gestalt.h = gestalt code
108 * QuickDraw.h = (included anyway)
109 * OSUtils.h = (included anyway)
110 * Files.h = file code
111 * Fonts.h = font code
112 * Menus.h = menu code
113 * Dialogs.h = dialog code
114 * Windows.h = (included anyway)
115 * Palettes.h = palette code
116 * StandardFile.h = file dialog box
117 * DiskInit.h = disk initialization
118 * ToolUtils.h = HiWord() / LoWord()
119 * Desk.h = OpenDeskAcc()
120 * Devices.h = OpenDeskAcc()
121 * Events.h = event code
122 * Resources.h = resource code
123 * Controls.h = button code
124 * SegLoad.h = ExitToShell(), AppFile, etc
125 * Memory.h = SetApplLimit(), NewPtr(), etc
126 * QDOffscreen.h = GWorld code
127 * Sound.h = Sound code
129 * For backwards compatibility:
130 * Use GestaltEqu.h instead of Gestalt.h
131 * Add Desk.h to include simply includes Menus.h, Devices.h, Events.h
139 #include <Carbon/Carbon.h>
140 #include <QuickTime/QuickTime.h>
141 #include <CoreServices/CoreServices.h>
142 #include <CoreFoundation/CoreFoundation.h>
144 #define TARGET_API_MAC_CARBON 1
146 #else /* MACH_O_CARBON */
150 #include <QuickDraw.h>
156 #include <Palettes.h>
157 #include <StandardFile.h>
158 #include <DiskInit.h>
159 #include <ToolUtils.h>
162 #include <Resources.h>
163 #include <Controls.h>
166 #include <QDOffscreen.h>
168 #if TARGET_API_MAC_CARBON
169 #include <Navigation.h>
170 #include <CFPreferences.h>
171 #include <CFNumber.h>
173 # include <CarbonStdCLib.h>
183 #endif /* MACH_O_CARBON */
186 * Use rewritten asynchronous sound player
188 #define USE_ASYNC_SOUND
191 * Cleaning up a couple of things to make these easier to change --AR
194 #define PREF_FILE_NAME "Hengband Preferences"
196 #define PREF_FILE_NAME "Hengband-E Preferences"
200 * Use "malloc()" instead of "NewPtr()"
202 /* #define USE_MALLOC */
205 /* Default creator signature */
206 #ifndef ANGBAND_CREATOR
207 # define ANGBAND_CREATOR 'Heng'
211 #if defined(powerc) || defined(__powerc)
214 * Disable "LITE" version
216 # undef ANGBAND_LITE_MAC
221 #ifdef ANGBAND_LITE_MAC
224 * Maximum number of windows
226 # define MAX_TERM_DATA 1
228 #else /* ANGBAND_LITE_MAC */
231 * Maximum number of windows
233 # define MAX_TERM_DATA 8
236 * Activate some special code
238 # define USE_SFL_CODE
240 #endif /* ANGBAND_LITE_MAC */
244 #ifndef MACH_O_CARBON
248 * Include the necessary header files
250 #include <AppleEvents.h>
255 #endif /* !MACH_O_CARBON */
258 * Globals for MPW compilation
260 #if defined(MACH_O_CARBON) || defined(MAC_MPW)
262 #if !TARGET_API_MAC_CARBON
274 * The Angband Color Set (0 to 15):
275 * Black, White, Slate, Orange, Red, Blue, Green, Umber
276 * D-Gray, L-Gray, Violet, Yellow, L-Red, L-Blue, L-Green, L-Umber
278 * Colors 8 to 15 are basically "enhanced" versions of Colors 0 to 7.
280 * On the Macintosh, we use color quickdraw, and we use actual "RGB"
281 * values below to choose the 16 colors.
283 * If we are compiled for ancient machines, we bypass color and simply
284 * draw everything in white (letting "z-term.c" automatically convert
285 * "black" into "wipe" calls).
287 static RGBColor foo[16] =
289 {0x0000, 0x0000, 0x0000}, /* TERM_DARK */
290 {0xFFFF, 0xFFFF, 0xFFFF}, /* TERM_WHITE */
291 {0x8080, 0x8080, 0x8080}, /* TERM_SLATE */
292 {0xFFFF, 0x8080, 0x0000}, /* TERM_ORANGE */
293 {0xC0C0, 0x0000, 0x0000}, /* TERM_RED */
294 {0x0000, 0x8080, 0x4040}, /* TERM_GREEN */
295 {0x0000, 0x0000, 0xFFFF}, /* TERM_BLUE */
296 {0x8080, 0x4040, 0x0000}, /* TERM_UMBER */
297 {0x4040, 0x4040, 0x4040}, /* TERM_L_DARK */
298 {0xC0C0, 0xC0C0, 0xC0C0}, /* TERM_L_WHITE */
299 {0xFFFF, 0x0000, 0xFFFF}, /* TERM_VIOLET */
300 {0xFFFF, 0xFFFF, 0x0000}, /* TERM_YELLOW */
301 {0xFFFF, 0x0000, 0x0000}, /* TERM_L_RED */
302 {0x0000, 0xFFFF, 0x0000}, /* TERM_L_GREEN */
303 {0x0000, 0xFFFF, 0xFFFF}, /* TERM_L_BLUE */
304 {0xC0C0, 0x8080, 0x4040} /* TERM_L_UMBER */
313 typedef struct term_data term_data;
326 #ifdef ANGBAND_LITE_MAC
330 #else /* ANGBAND_LITE_MAC */
342 #endif /* ANGBAND_LITE_MAC */
385 * Forward declare -- see below
387 static bool CheckEvents(bool wait);
389 #ifndef MACH_O_CARBON
392 * Hack -- location of the main directory
394 static short app_vol;
397 #endif /* !MACH_O_CARBON */
400 * Delay handling of double-clicked savefiles
402 Boolean open_when_ready = FALSE;
405 * Delay handling of pre-emptive "quit" event
407 Boolean quit_when_ready = FALSE;
411 * Hack -- game in progress
413 static int game_in_progress = 0;
417 * Only do "SetPort()" when needed
419 static WindowPtr active = NULL;
424 * An array of term_data's
426 static term_data data[MAX_TERM_DATA];
431 * Note when "open"/"new" become valid
433 static bool initialized = FALSE;
436 * Version of Mac OS - for version specific bug workarounds (; ;)
438 static long mac_os_version;
441 #if defined(__MWERKS__)
443 * CodeWarrior uses Universal Procedure Pointers
445 static ModalFilterUPP ynfilterUPP;
447 #endif /* __MWERKS__ */
454 AEEventHandlerUPP AEH_Start_UPP;
455 AEEventHandlerUPP AEH_Quit_UPP;
456 AEEventHandlerUPP AEH_Print_UPP;
457 AEEventHandlerUPP AEH_Open_UPP;
461 # ifdef USE_ASYNC_SOUND
464 * Asynchronous sound player revised
466 #if defined(USE_QT_SOUND) && !defined(MACH_O_CARBON)
468 #endif /* USE_QT_SOUND && !MACH_O_CARBON */
472 * Number of channels in the channel pool
474 #if TARGET_API_MAC_CARBON
475 #define MAX_CHANNELS 8
477 #define MAX_CHANNELS 4
481 * A pool of sound channels
483 static SndChannelPtr channels[MAX_CHANNELS];
486 * Status of the channel pool
488 static Boolean channel_initialised = FALSE;
491 * Data handles containing sound samples
493 static SndListHandle samples[SOUND_MAX];
496 * Reference counts of sound samples
498 static SInt16 sample_refs[SOUND_MAX];
504 * These constants aren't used by the program at the moment.
506 #define SOUND_VOLUME_MIN 0 /* Default minimum sound volume */
507 #define SOUND_VOLUME_MAX 255 /* Default maximum sound volume */
508 #define VOLUME_MIN 0 /* Minimum sound volume in % */
509 #define VOLUME_MAX 100 /* Maximum sound volume in % */
510 #define VOLUME_INC 5 /* Increment sound volume in % */
512 /* I'm just too lazy to write a panel for this XXX XXX */
513 static SInt16 sound_volume = SOUND_VOLUME_MAX;
518 * Moving graphics resources into data fork -- pelpel
521 * Given base and type names of a resource, find a file in the
522 * current application bundle and return its FSSpec in the third argument.
523 * Returns true on success, false otherwise.
524 * e.g. get_resource_spec(CFSTR("8x8"), CFSTR("png"), &spec);
526 static Boolean get_resource_spec(
527 CFStringRef base_name, CFStringRef type_name, FSSpec *spec)
532 /* Find resource (=file) in the current bundle */
533 res_url = CFBundleCopyResourceURL(
534 CFBundleGetMainBundle(), base_name, type_name, NULL);
537 if (res_url == NULL) return (false);
539 /* Convert CFURL to FSRef */
540 (void)CFURLGetFSRef(res_url, &ref);
542 /* Convert FSRef to FSSpec */
543 (void)FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
545 /* Free allocated CF data */
553 * QuickTime sound, by Ron Anderson
555 * I didn't choose to use Windows-style .ini files (Ron wrote a parser
556 * for it, but...), nor did I use lib/xtra directory, hoping someone
557 * would code plist-based configuration code in the future -- pelpel
562 * Load sound effects from data-fork resources. They are wav files
563 * with the same names as angband_sound_name[] (variable.c)
565 * Globals referenced: angband_sound_name[]
566 * Globals updated: samples[] (they can be *huge*)
568 static void load_sounds(void)
573 /* Start QuickTime */
577 if (err != noErr) return;
580 * This loop may take a while depending on the count and size of samples
583 * We should use a progress dialog for this.
585 for (i = 1; i < SOUND_MAX; i++)
587 /* Apple APIs always give me headacke :( */
598 /* Allocate CFString with the name of sound event to be processed */
599 name = CFStringCreateWithCString(NULL, angband_sound_name[i],
600 kTextEncodingUS_ASCII);
603 if (name == NULL) continue;
605 /* Find sound sample resource with the same name */
606 res = get_resource_spec(name, CFSTR("wav"), &spec);
608 /* Free the reference to CFString */
614 /* Open the sound file */
615 err = OpenMovieFile(&spec, &file_id, fsRdPerm);
618 if (err != noErr) continue;
620 /* Create Movie from the file */
621 err = NewMovieFromFile(&movie, file_id, &res_id, movie_name,
622 newMovieActive, NULL);
625 if (err != noErr) goto close_file;
627 /* Get the first track of the movie */
628 track = GetMovieIndTrackType(movie, 1, AudioMediaCharacteristic,
629 movieTrackCharacteristic | movieTrackEnabledOnly );
632 if (track == NULL) goto close_movie;
634 /* Allocate a handle to store sample */
638 if (h == NULL) goto close_track;
640 /* Dump the sample into the handle */
641 err = PutMovieIntoTypedHandle(movie, track, soundListRsrc, h, 0,
642 GetTrackDuration(track), 0L, NULL);
647 /* Store the handle in the sample list */
648 samples[i] = (SndListHandle)h;
654 /* Free unused handle */
659 close_track: DisposeMovieTrack(track);
662 close_movie: DisposeMovie(movie);
664 /* Close the movie file */
665 close_file: CloseMovieFile(file_id);
672 #else /* USE_QT_SOUND */
675 * Return a handle of 'snd ' resource given Angband sound event number,
676 * or NULL if it isn't found.
678 * Globals referenced: angband_sound_name[] (variable.c)
680 static SndListHandle find_sound(int num)
684 /* Get the proper sound name */
685 strnfmt((char*)sound + 1, 255, "%.16s.wav", angband_sound_name[num]);
686 sound[0] = strlen((char*)sound + 1);
688 /* Obtain resource XXX XXX XXX */
689 return ((SndListHandle)GetNamedResource('snd ', sound));
692 #endif /* USE_QT_SOUND */
696 * Clean up sound support - to be called when the game exits.
698 * Globals referenced: channels[], samples[], sample_refs[].
700 static void cleanup_sound(void)
704 /* No need to clean it up */
705 if (!channel_initialised) return;
707 /* Dispose channels */
708 for (i = 0; i < MAX_CHANNELS; i++)
710 /* Drain sound commands and free the channel */
711 SndDisposeChannel(channels[i], TRUE);
714 /* Free sound data */
715 for (i = 1; i < SOUND_MAX; i++)
718 if ((sample_refs[i] > 0) && (samples[i] != NULL))
721 HUnlock((Handle)samples[i]);
727 if (samples[i]) ReleaseResource((Handle)samples[i]);
731 if (samples[i]) DisposeHandle((Handle)samples[i]);
732 #endif /* !USE_QT_SOUND */
738 * Play sound effects asynchronously -- pelpel
740 * I don't believe those who first started using the previous implementations
741 * imagined this is *much* more complicated as it may seem. Anyway,
742 * introduced round-robin scheduling of channels and made it much more
743 * paranoid about HLock/HUnlock.
745 * XXX XXX de-refcounting, HUnlock and ReleaseResource should be done
746 * using channel's callback procedures, which set global flags, and
747 * a procedure hooked into CheckEvents does housekeeping. On the other
748 * hand, this lazy reclaiming strategy keeps things simple (no interrupt
749 * time code) and provides a sort of cache for sound data.
751 * Globals referenced: channel_initialised, channels[], samples[],
753 * Globals updated: ditto.
755 static void play_sound(int num, SInt16 vol)
764 static int next_chan;
765 static SInt16 channel_occupants[MAX_CHANNELS];
766 static SndCommand volume_cmd, quiet_cmd;
769 /* Initialise sound channels */
770 if (!channel_initialised)
772 for (i = 0; i < MAX_CHANNELS; i++)
774 /* Paranoia - Clear occupant table */
775 /* channel_occupants[i] = 0; */
777 /* Create sound channel for all sounds to play from */
778 err = SndNewChannel(&channels[i], sampledSynth, initMono, 0L);
786 SndDisposeChannel(channels[i], TRUE);
791 plog("¥µ¥¦¥ó¥É¥Á¥ã¥ó¥Í¥ë¤ò½é´ü²½½ÐÍè¤Þ¤»¤ó!");
793 plog("Cannot initialise sound channels!");
797 use_sound = arg_sound = FALSE;
804 /* First channel to use */
807 /* Prepare volume command */
808 volume_cmd.cmd = volumeCmd;
809 volume_cmd.param1 = 0;
810 volume_cmd.param2 = 0;
812 /* Prepare quiet command */
813 quiet_cmd.cmd = quietCmd;
814 quiet_cmd.param1 = 0;
815 quiet_cmd.param2 = 0;
817 /* Initialisation complete */
818 channel_initialised = TRUE;
822 if ((num <= 0) || (num >= SOUND_MAX)) return;
824 /* Prepare volume command */
825 volume_cmd.param2 = ((SInt32)vol << 16) | vol;
827 /* Channel to use (round robin) */
828 chan = channels[next_chan];
830 /* See if the resource is already in use */
831 if (sample_refs[num] > 0)
833 /* Resource in use */
836 /* Increase the refcount */
840 /* Sound is not currently in use */
843 /* Get handle for the sound */
848 #endif /* USE_QT_SOUND */
850 /* Sample not available */
851 if (h == NULL) return;
856 LoadResource((Handle)h);
861 #endif /* !USE_QT_SOUND */
863 /* Lock the handle */
866 /* Initialise refcount */
867 sample_refs[num] = 1;
870 /* Poll the channel */
871 err = SndChannelStatus(chan, sizeof(SCStatus), &status);
873 /* It isn't available */
874 if ((err != noErr) || status.scChannelBusy)
877 SndDoImmediate(chan, &quiet_cmd);
880 /* Previously played sound on this channel */
881 prev_num = channel_occupants[next_chan];
883 /* Process previously played sound */
886 /* Decrease refcount */
887 sample_refs[prev_num]--;
889 /* We can free it now */
890 if (sample_refs[prev_num] <= 0)
893 HUnlock((Handle)samples[prev_num]);
898 ReleaseResource((Handle)samples[prev_num]);
901 samples[prev_num] = NULL;
903 #endif /* !USE_QT_SOUND */
906 sample_refs[prev_num] = 0;
910 /* Remember this sound as the current occupant of the channel */
911 channel_occupants[next_chan] = num;
913 /* Set up volume for channel */
914 SndDoImmediate(chan, &volume_cmd);
916 /* Play new sound asynchronously */
917 SndPlay(chan, h, TRUE);
919 /* Schedule next channel (round robin) */
921 if (next_chan >= MAX_CHANNELS) next_chan = 0;
924 # else /* USE_ASYNC_SOUND */
927 * Play sound synchronously
929 * This may not be your choice, but much safer and much less resource hungry.
931 static void play_sound(int num, SInt16 vol)
936 /* Get the proper sound name */
937 strnfmt((char*)sound + 1, 255, "%.16s.wav", angband_sound_name[num]);
938 sound[0] = strlen((char*)sound + 1);
940 /* Obtain resource XXX XXX XXX */
941 handle = GetNamedResource('snd ', sound);
944 if (handle == NULL) return;
947 LoadResource(handle);
950 /* Play sound (wait for completion) */
951 SndPlay(NULL, (SndListHandle)handle, FALSE);
953 /* Unlock and release */
955 ReleaseResource(handle);
958 # endif /* USE_ASYNC_SOUND */
960 #ifndef MACH_O_CARBON
966 static int ext_sound = 0;
974 #define SND_CMD_ERROR 6
976 static int soundchoice[] = {
1044 static int ext_graf = 0;
1046 #endif /* !MACH_O_CARBON */
1048 static short soundmode[8];
1052 * Convert refnum+vrefnum+fname into a full file name
1053 * Store this filename in 'buf' (make sure it is long enough)
1054 * Note that 'fname' looks to be a "pascal" string
1056 #if TARGET_API_MAC_CARBON
1057 static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname)
1072 for (j=1; j<=fname[0]; j++)
1074 res[i-fname[0]+j] = fname[j];
1083 pb.dirInfo.ioDrDirID=pb.dirInfo.ioDrParID;
1084 err = FSMakeFSSpec( vref, dirID, "\p", &spec );
1090 for (j=1; j<=spec.name[0]; j++)
1092 res[i-spec.name[0]+j] = spec.name[j];
1099 /* Extract the result */
1100 for (j = 0, i++; res[i]; j++, i++) buf[j] = res[i];
1104 static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname)
1116 for (j=1; j<=fname[0]; j++)
1118 res[i-fname[0]+j] = fname[j];
1122 pb.ioCompletion=NULL;
1124 pb.ioVRefNum=vrefnum;
1125 pb.ioDrParID=refnum;
1130 pb.ioDrDirID=pb.ioDrParID;
1131 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
1133 for (j=1; j<=name[0]; j++)
1135 res[i-name[0]+j] = name[j];
1139 if (pb.ioDrDirID == fsRtDirID) break;
1142 /* Extract the result */
1143 for (j = 0, i++; res[i]; j++, i++) buf[j] = res[i];
1148 #if TARGET_API_MAC_CARBON
1149 pascal OSErr FSpLocationFromFullPath(short fullPathLength,
1150 const void *fullPath,
1158 /* Create a minimal alias from the full pathname */
1159 nullString[0] = 0; /* null string to indicate no zone or server name */
1160 result = NewAliasMinimalFromFullPath(fullPathLength, fullPath, nullString, nullString, &alias);
1161 if ( result == noErr )
1163 /* Let the Alias Manager resolve the alias. */
1164 result = ResolveAlias(NULL, alias, spec, &wasChanged);
1166 /* work around Alias Mgr sloppy volume matching bug */
1167 if ( spec->vRefNum == 0 )
1169 /* invalidate wrong FSSpec */
1174 DisposeHandle((Handle)alias); /* Free up memory used */
1183 * XXX XXX XXX Allow the system to ask us for a filename
1185 static bool askfor_file(char *buf, int len)
1193 /* Default file name */
1194 sprintf((char*)dflt + 1, "%s's description", buf);
1195 dflt[0] = strlen((char*)dflt + 1);
1197 /* Ask for a file name */
1198 topleft.h=(qd.screenBits.bounds.left+qd.screenBits.bounds.right)/2-344/2;
1199 topleft.v=(2*qd.screenBits.bounds.top+qd.screenBits.bounds.bottom)/3-188/2;
1200 SFPutFile(topleft, "\pSelect a filename:", dflt, NULL, &reply);
1201 /* StandardPutFile("\pSelect a filename:", dflt, &reply); */
1209 GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
1211 /* Extract the name */
1212 refnum_to_name(buf, drefnum, vrefnum, (char*)reply.fName);
1224 #if !TARGET_API_MAC_CARBON
1225 static void local_to_global( Rect *r )
1232 LocalToGlobal( &temp );
1240 LocalToGlobal( &temp );
1245 #endif /* !TARGET_API_MAC_CARBON */
1247 static void global_to_local( Rect *r )
1254 GlobalToLocal( &temp );
1262 GlobalToLocal( &temp );
1272 * Convert pathname to an appropriate format, because MPW's
1273 * CarbonStdCLib chose to use system's native path format,
1274 * making our lives harder to create binaries that run on
1275 * OS 8/9 and OS X :( -- pelpel
1277 void convert_pathname(char* path)
1281 /* Nothing has to be done for CarbonLib on Classic */
1282 if (mac_os_version >= 0x1000)
1284 /* Convert to POSIX style */
1285 ConvertHFSPathToUnixPath(path, buf);
1287 /* Copy the result back */
1295 # ifdef CHECK_MODIFICATION_TIME
1298 * Although there is no easy way to emulate fstat in the old interface,
1299 * we still can do stat-like things, because Mac OS is an OS.
1301 static int get_modification_time(cptr path, u32b *mod_time)
1307 /* Paranoia - make sure the pathname fits in Str255 */
1309 if (i > 255) return (-1);
1311 /* Convert pathname to a Pascal string */
1312 strncpy((char *)pathname + 1, path, 255);
1315 /* Set up parameter block */
1316 pb.hFileInfo.ioNamePtr = pathname;
1317 pb.hFileInfo.ioFDirIndex = 0;
1318 pb.hFileInfo.ioVRefNum = app_vol;
1319 pb.hFileInfo.ioDirID = 0;
1321 /* Get catalog information of the file */
1322 if (PBGetCatInfoSync(&pb) != noErr) return (-1);
1324 /* Set modification date and time */
1325 *mod_time = pb.hFileInfo.ioFlMdDat;
1333 * A (non-Mach-O) Mac OS version of check_modification_time, for those
1334 * compilers without good enough POSIX-compatibility libraries XXX XXX
1336 errr check_modification_date(int fd, cptr template_file)
1339 u32b txt_stat, raw_stat;
1344 /* Build the file name */
1345 path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, template_file);
1348 convert_pathname(buf);
1350 /* Obtain modification time */
1351 if (get_modification_time(buf, &txt_stat)) return (-1);
1353 /* XXX Build filename of the corresponding *.raw file */
1354 strnfmt(fname, sizeof(fname), "%s", template_file);
1357 p = strrchr(fname, '.');
1360 if (p == NULL) return (-1);
1362 /* Substitute ".raw" for ".txt" */
1365 /* Build the file name of the raw file */
1366 path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, fname);
1369 convert_pathname(buf);
1371 /* Obtain modification time */
1372 if (get_modification_time(buf, &raw_stat)) return (-1);
1374 /* Ensure the text file is not newer than the raw file */
1375 if (txt_stat > raw_stat) return (-1);
1377 /* Keep using the current .raw file */
1381 # endif /* CHECK_MODIFICATION_TIME */
1383 #endif /* MAC_MPW */
1386 * Center a rectangle inside another rectangle
1388 static void center_rect(Rect *r, Rect *s)
1390 int centerx = (s->left + s->right)/2;
1391 int centery = (2*s->top + s->bottom)/3;
1392 int dx = centerx - (r->right - r->left)/2 - r->left;
1393 int dy = centery - (r->bottom - r->top)/2 - r->top;
1401 #ifdef MACH_O_CARBON
1403 /* Carbon File Manager utilities by pelpel */
1407 * Convert a pathname to a corresponding FSSpec.
1408 * Returns noErr on success.
1410 static OSErr path_to_spec(const char *path, FSSpec *spec)
1415 /* Convert pathname to FSRef ... */
1416 err = FSPathMakeRef(path, &ref, NULL);
1417 if (err != noErr) return (err);
1419 /* ... then FSRef to FSSpec */
1420 err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
1422 /* Inform caller of success or failure */
1429 * Convert a FSSpec to a corresponding pathname.
1430 * Returns noErr on success.
1432 static OSErr spec_to_path(const FSSpec *spec, char *buf, size_t size)
1437 /* Convert FSSpec to FSRef ... */
1438 err = FSpMakeFSRef(spec, &ref);
1439 if (err != noErr) return (err);
1441 /* ... then FSRef to pathname */
1442 err = FSRefMakePath(&ref, buf, size);
1444 /* Inform caller of success or failure */
1450 * (Carbon) [via path_to_spec]
1451 * Set creator and filetype of a file specified by POSIX-style pathname.
1452 * Returns 0 on success, -1 in case of errors.
1454 void fsetfileinfo(cptr pathname, OSType fcreator, OSType ftype)
1460 /* Convert pathname to FSSpec */
1461 if (path_to_spec(pathname, &spec) != noErr) return;
1463 /* Obtain current finder info of the file */
1464 if (FSpGetFInfo(&spec, &info) != noErr) return;
1466 /* Overwrite creator and type */
1467 info.fdCreator = fcreator;
1468 info.fdType = ftype;
1469 err = FSpSetFInfo(&spec, &info);
1476 #else /* MACH_O_CARBON */
1480 * Convert a pascal string in place
1482 * This function may be defined elsewhere, but since it is so
1483 * small, it is not worth finding the proper function name for
1484 * all the different platforms.
1486 static void ptocstr(StringPtr src)
1490 /* Hack -- pointer */
1491 char *s = (char*)(src);
1493 /* Hack -- convert the string */
1494 for (i = s[0]; i; i--, s++) s[0] = s[1];
1496 /* Hack -- terminate the string */
1501 #if defined(USE_SFL_CODE)
1505 * The following three routines (pstrcat, pstrinsert, and PathNameFromDirID)
1506 * were taken from the Think Reference section called "Getting a Full Pathname"
1507 * (under the File Manager section). We need PathNameFromDirID to get the
1508 * full pathname of the opened savefile, making no assumptions about where it
1511 * I had to hack PathNameFromDirID a little for MetroWerks, but it's awfully
1514 static void pstrcat(StringPtr dst, StringPtr src)
1516 /* copy string in */
1517 BlockMove(src + 1, dst + *dst + 1, *src);
1519 /* adjust length byte */
1524 * pstrinsert - insert string 'src' at beginning of string 'dst'
1526 static void pstrinsert(StringPtr dst, StringPtr src)
1528 /* make room for new string */
1529 BlockMove(dst + 1, dst + *src + 1, *dst);
1531 /* copy new string in */
1532 BlockMove(src + 1, dst + 1, *src);
1534 /* adjust length byte */
1538 static void PathNameFromDirID(long dirID, short vRefNum, StringPtr fullPathName)
1541 Str255 directoryName;
1544 fullPathName[0] = '\0';
1546 block.dirInfo.ioDrParID = dirID;
1547 block.dirInfo.ioNamePtr = directoryName;
1551 block.dirInfo.ioVRefNum = vRefNum;
1552 block.dirInfo.ioFDirIndex = -1;
1553 block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID;
1554 err = PBGetCatInfo(&block, FALSE);
1555 pstrcat(directoryName, (StringPtr)"\p:");
1556 pstrinsert(fullPathName, directoryName);
1557 if (block.dirInfo.ioDrDirID == 2) break;
1562 #endif /* MACH_O_CARBON */
1565 * Activate a given window, if necessary
1567 static void activate(WindowPtr w)
1573 #if TARGET_API_MAC_CARBON
1574 if (w) SetPortWindowPort(w);
1586 * Display a warning message
1588 static void mac_warning(cptr warning)
1593 /* Limit of 250 chars */
1594 len = strlen(warning);
1595 if (len > 250) len = 250;
1597 /* Make a "Pascal" string */
1599 for (i=0; i<len; i++) text[i+1] = warning[i];
1601 /* Prepare the dialog box values */
1602 ParamText(text, "\p", "\p", "\p");
1604 /* Display the Alert, wait for Okay */
1610 /*** Some generic functions ***/
1613 #ifdef ANGBAND_LITE_MAC
1616 * Hack -- activate a color (0 to 255)
1618 #define term_data_color(TD,A) /* Nothing */
1620 #else /* ANGBAND_LITE_MAC */
1623 * Hack -- activate a color (0 to 255)
1625 static void term_data_color(term_data *td, int a)
1631 /* Extract the R,G,B data */
1632 rv = angband_color_table[a][1];
1633 gv = angband_color_table[a][2];
1634 bv = angband_color_table[a][3];
1637 color.red = (rv | (rv << 8));
1638 color.green = (gv | (gv << 8));
1639 color.blue = (bv | (bv << 8));
1641 /* Activate the color */
1642 RGBForeColor(&color);
1644 /* Memorize color */
1648 #endif /* ANGBAND_LITE_MAC */
1652 * Hack -- Apply and Verify the "font" info
1654 * This should usually be followed by "term_data_check_size()"
1656 static void term_data_check_font(term_data *td)
1662 WindowPtr old = active;
1668 /* Instantiate font */
1669 TextFont(td->font_id);
1670 TextSize(td->font_size);
1671 TextFace(td->font_face);
1673 /* Extract the font info */
1676 /* Assume monospaced */
1677 td->font_mono = TRUE;
1679 /* Extract the font sizing values XXX XXX XXX */
1680 td->font_wid = CharWidth('@'); /* info.widMax; */
1681 td->font_hgt = info.ascent + info.descent;
1683 td->font_o_y = info.ascent;
1685 /* Check important characters */
1686 for (i = 33; i < 127; i++)
1688 /* Hack -- notice non-mono-space */
1689 if (td->font_wid != CharWidth(i)) td->font_mono = FALSE;
1691 /* Hack -- collect largest width */
1692 if (td->font_wid < CharWidth(i)) td->font_wid = CharWidth(i);
1695 /* Set default offsets */
1696 td->tile_o_x = td->font_o_x;
1697 td->tile_o_y = td->font_o_y;
1699 /* Set default tile size */
1700 if( td->tile_wid == 0 && td->tile_hgt == 0 ){
1701 td->tile_wid = td->font_wid;
1702 td->tile_hgt = td->font_hgt;
1705 /* Re-activate the old window */
1711 * Hack -- Apply and Verify the "size" info
1713 static void term_data_check_size(term_data *td)
1717 #if TARGET_API_MAC_CARBON
1718 GetQDGlobalsScreenBits( &screen );
1720 screen = qd.screenBits;
1722 /* Minimal window size */
1725 /* Enforce minimal size */
1726 if (td->cols < 80) td->cols = 80;
1727 if (td->rows < 24) td->rows = 24;
1730 /* Allow small windows for the rest */
1733 if (td->cols < 1) td->cols = 1;
1734 if (td->rows < 1) td->rows = 1;
1737 /* Minimal tile size */
1738 if (td->tile_wid < 4) td->tile_wid = 4;
1739 if (td->tile_hgt < 4) td->tile_hgt = 4;
1741 /* Default tile offsets */
1742 td->tile_o_x = (td->tile_wid - td->font_wid) / 2;
1743 td->tile_o_y = (td->tile_hgt - td->font_hgt) / 2;
1745 /* Minimal tile offsets */
1746 if (td->tile_o_x < 0) td->tile_o_x = 0;
1747 if (td->tile_o_y < 0) td->tile_o_y = 0;
1749 /* Apply font offsets */
1750 td->tile_o_x += td->font_o_x;
1751 td->tile_o_y += td->font_o_y;
1753 /* Calculate full window size */
1754 td->size_wid = td->cols * td->tile_wid + td->size_ow1 + td->size_ow2;
1755 td->size_hgt = td->rows * td->tile_hgt + td->size_oh1 + td->size_oh2;
1757 /* Verify the top */
1758 if (td->r.top > screen.bounds.bottom - td->size_hgt)
1760 td->r.top = screen.bounds.bottom - td->size_hgt;
1763 /* Verify the top */
1764 if (td->r.top < screen.bounds.top + 30)
1766 td->r.top = screen.bounds.top + 30;
1769 /* Verify the left */
1770 if (td->r.left > screen.bounds.right - td->size_wid)
1772 td->r.left = screen.bounds.right - td->size_wid;
1775 /* Verify the left */
1776 if (td->r.left < screen.bounds.left)
1778 td->r.left = screen.bounds.left;
1781 /* Calculate bottom right corner */
1782 td->r.right = td->r.left + td->size_wid;
1783 td->r.bottom = td->r.top + td->size_hgt;
1785 /* Assume no graphics */
1786 td->t->higher_pict = FALSE;
1787 td->t->always_pict = FALSE;
1789 #ifdef ANGBAND_LITE_MAC
1793 #else /* ANGBAND_LITE_MAC */
1795 /* Handle graphics */
1798 /* Use higher_pict whenever possible */
1799 if (td->font_mono) td->t->higher_pict = TRUE;
1801 /* Use always_pict only when necessary */
1802 else td->t->always_pict = TRUE;
1805 #endif /* ANGBAND_LITE_MAC */
1807 /* Fake mono-space */
1808 if (!td->font_mono ||
1809 (td->font_wid != td->tile_wid) ||
1810 (td->font_hgt != td->tile_hgt))
1812 /* Handle fake monospace -- this is SLOW */
1813 if (td->t->higher_pict) td->t->higher_pict = FALSE;
1814 td->t->always_pict = TRUE;
1819 * Hack -- resize a term_data
1821 * This should normally be followed by "term_data_resize()"
1823 static void term_data_resize(term_data *td)
1825 /* Actually resize the window */
1826 SizeWindow(td->w, td->size_wid, td->size_hgt, 0);
1832 * Hack -- redraw a term_data
1834 * Note that "Term_redraw()" calls "TERM_XTRA_CLEAR"
1836 static void term_data_redraw(term_data *td)
1840 /* Activate the term */
1841 Term_activate(td->t);
1843 /* Redraw the contents */
1846 /* Flush the output */
1849 /* Restore the old term */
1852 /* No need to redraw */
1853 #if TARGET_API_MAC_CARBON
1855 RgnHandle theRgn = NewRgn();
1856 GetWindowRegion( td->w, kWindowContentRgn, theRgn );
1857 ValidWindowRgn( (WindowRef)(td->w), theRgn );
1858 DisposeRgn( theRgn );
1861 ValidRect(&td->w->portRect);
1869 #ifdef ANGBAND_LITE_MAC
1873 #else /* ANGBAND_LITE_MAC */
1880 static int pictID = 1001; /* 8x8 tiles; 16x16 tiles are 1002 */
1882 static int grafWidth = 8; /* Always equal to grafHeight */
1883 static int grafHeight = 8; /* Either 8 or 16 */
1885 static bool arg_newstyle_graphics;
1886 static bool use_newstyle_graphics;
1891 typedef struct FrameRec FrameRec;
1896 * - GWorld for the frame image
1897 * - Handle to pix map (saved for unlocking/locking)
1898 * - Pointer to color pix map (valid only while locked)
1902 GWorldPtr framePort;
1903 PixMapHandle framePixHndl;
1910 * The global picture data
1912 static FrameRec *frameP = NULL;
1918 static void BenSWLockFrame(FrameRec *srcFrameP)
1920 PixMapHandle pixMapH;
1922 pixMapH = GetGWorldPixMap(srcFrameP->framePort);
1923 (void)LockPixels(pixMapH);
1924 HLockHi((Handle)pixMapH);
1925 srcFrameP->framePixHndl = pixMapH;
1926 #if TARGET_API_MAC_CARBON
1927 srcFrameP->framePix = (PixMapPtr)*(Handle)pixMapH;
1929 srcFrameP->framePix = (PixMapPtr)StripAddress(*(Handle)pixMapH);
1938 static void BenSWUnlockFrame(FrameRec *srcFrameP)
1940 if (srcFrameP->framePort != NULL)
1942 HUnlock((Handle)srcFrameP->framePixHndl);
1943 UnlockPixels(srcFrameP->framePixHndl);
1946 srcFrameP->framePix = NULL;
1950 static OSErr BenSWCreateGWorldFromPict(
1951 GWorldPtr *pictGWorld,
1955 GWorldPtr saveGWorld;
1956 GDHandle saveGDevice;
1957 GWorldPtr tempGWorld;
1966 depth = data[0].pixelDepth;
1969 theGDH = data[0].theGDH;
1971 /* Obtain size rectangle */
1972 pictRect = (**pictH).picFrame;
1973 OffsetRect(&pictRect, -pictRect.left, -pictRect.top);
1975 /* Create a GWorld */
1976 err = NewGWorld(&tempGWorld, depth, &pictRect, nil,
1977 theGDH, noNewDevice);
1986 *pictGWorld = tempGWorld;
1989 GetGWorld(&saveGWorld, &saveGDevice);
1992 SetGWorld(tempGWorld, nil);
1994 /* Dump the pict into the GWorld */
1995 (void)LockPixels(GetGWorldPixMap(tempGWorld));
1996 EraseRect(&pictRect);
1997 DrawPicture(pictH, &pictRect);
1998 UnlockPixels(GetGWorldPixMap(tempGWorld));
2000 /* Restore GWorld */
2001 SetGWorld(saveGWorld, saveGDevice);
2011 * Init the global "frameP"
2014 static errr globe_init(void)
2018 GWorldPtr tempPictGWorldP;
2022 /* Use window XXX XXX XXX */
2023 #if TARGET_API_MAC_CARBON
2024 SetPortWindowPort(data[0].w);
2030 /* Get the pict resource */
2031 newPictH = GetPicture(pictID);
2033 /* Analyze result */
2034 err = (newPictH ? 0 : -1);
2041 err = BenSWCreateGWorldFromPict(&tempPictGWorldP, newPictH);
2043 /* Release resource */
2044 ReleaseResource((Handle)newPictH);
2049 /* Create the frame */
2050 frameP = (FrameRec*)NewPtrClear((Size)sizeof(FrameRec));
2052 /* Analyze result */
2053 err = (frameP ? 0 : -1);
2059 frameP->framePort = tempPictGWorldP;
2062 BenSWLockFrame(frameP);
2073 * Nuke the global "frameP"
2075 static errr globe_nuke(void)
2081 BenSWUnlockFrame(frameP);
2083 /* Dispose of the GWorld */
2084 DisposeGWorld(frameP->framePort);
2086 /* Dispose of the memory */
2087 DisposePtr((Ptr)frameP);
2094 FlushEvents(everyEvent, 0);
2101 #endif /* ANGBAND_LITE_MAC */
2105 /*** Support for the "z-term.c" package ***/
2109 * Initialize a new Term
2111 * Note also the "window type" called "noGrowDocProc", which might be more
2112 * appropriate for the main "screen" window.
2114 * Note the use of "srcCopy" mode for optimized screen writes.
2116 static void Term_init_mac(term *t)
2118 term_data *td = (term_data*)(t->data);
2120 static RGBColor black = {0x0000,0x0000,0x0000};
2121 static RGBColor white = {0xFFFF,0xFFFF,0xFFFF};
2123 #ifdef ANGBAND_LITE_MAC
2125 /* Make the window */
2126 td->w = NewWindow(0, &td->r, td->title, 0, noGrowDocProc, (WindowPtr)-1, 1, 0L);
2128 #else /* ANGBAND_LITE_MAC */
2130 /* Make the window */
2131 td->w = NewCWindow(0, &td->r, td->title, 0, documentProc, (WindowPtr)-1, 1, 0L);
2133 #endif /* ANGBAND_LITE_MAC */
2135 /* Activate the window */
2138 /* Erase behind words */
2141 /* Apply and Verify */
2142 term_data_check_font(td);
2143 term_data_check_size(td);
2145 /* Resize the window */
2146 term_data_resize(td);
2148 #ifdef ANGBAND_LITE_MAC
2150 /* Prepare the colors (base colors) */
2151 BackColor(blackColor);
2152 ForeColor(whiteColor);
2154 #else /* ANGBAND_LITE_MAC */
2156 /* Prepare the colors (real colors) */
2157 RGBBackColor(&black);
2158 RGBForeColor(&white);
2164 GDHandle currentGDH;
2165 GWorldPtr windowGWorld;
2166 PixMapHandle basePixMap;
2168 /* Obtain the rect */
2169 #if TARGET_API_MAC_CARBON
2170 GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &globalRect );
2172 globalRect = td->w->portRect;
2173 LocalToGlobal((Point*)&globalRect.top);
2174 LocalToGlobal((Point*)&globalRect.bottom);
2177 /* Obtain the proper GDH */
2178 mainGDH = GetMaxDevice(&globalRect);
2180 /* Extract GWorld and GDH */
2181 GetGWorld(&windowGWorld, ¤tGDH);
2183 /* Obtain base pixmap */
2184 basePixMap = (**mainGDH).gdPMap;
2186 /* Save pixel depth */
2187 td->pixelDepth = (**basePixMap).pixelSize;
2189 /* Save Window GWorld */
2190 td->theGWorld = windowGWorld;
2192 /* Save Window GDH */
2193 td->theGDH = currentGDH;
2196 td->mainSWGDH = mainGDH;
2199 #endif /* ANGBAND_LITE_MAC */
2204 #if TARGET_API_MAC_CARBON
2205 GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &portRect );
2206 global_to_local( &portRect );
2208 portRect = td->w->portRect;
2210 /* Clip to the window */
2211 ClipRect(&portRect);
2213 /* Erase the window */
2214 EraseRect(&portRect);
2216 /* Invalidate the window */
2217 #if TARGET_API_MAC_CARBON
2218 InvalWindowRect((WindowRef)(td->w), (const Rect *)(&portRect));
2220 InvalRect(&portRect);
2223 /* Display the window if needed */
2224 if (td->mapped) ShowWindow(td->w);
2226 /* Hack -- set "mapped" flag */
2227 t->mapped_flag = td->mapped;
2233 /* if (err == noErr)
2244 static void Term_nuke_mac(term *t)
2257 static errr Term_user_mac(int n)
2271 static errr Term_xtra_mac_react(void)
2273 term_data *td = (term_data*)(Term->data);
2279 #ifdef ANGBAND_LITE_MAC
2283 #else /* ANGBAND_LITE_MAC */
2286 if (use_sound != arg_sound)
2289 use_sound = arg_sound;
2293 /* Handle transparency */
2294 if (use_newstyle_graphics != arg_newstyle_graphics)
2298 if (globe_init() != 0)
2300 plog("Cannot initialize graphics!");
2301 arg_graphics = FALSE;
2302 arg_newstyle_graphics = FALSE;
2306 use_newstyle_graphics = arg_newstyle_graphics;
2308 /* Apply and Verify */
2309 term_data_check_size(td);
2311 /* Resize the window */
2312 term_data_resize(td);
2318 /* Handle graphics */
2319 if (use_graphics != arg_graphics)
2321 /* Initialize graphics */
2323 if (!use_graphics && !frameP && (globe_init() != 0))
2326 plog("¥°¥é¥Õ¥£¥Ã¥¯¤Î½é´ü²½¤Ï½ÐÍè¤Þ¤»¤ó¤Ç¤·¤¿.");
2328 plog("Cannot initialize graphics!");
2330 arg_graphics = FALSE;
2334 use_graphics = arg_graphics;
2336 /* Apply and Verify */
2337 term_data_check_size(td);
2339 /* Resize the window */
2340 term_data_resize(td);
2346 #endif /* ANGBAND_LITE_MAC */
2354 * Do a "special thing"
2356 static errr Term_xtra_mac(int n, int v)
2358 term_data *td = (term_data*)(Term->data);
2366 case TERM_XTRA_NOISE:
2375 #ifdef ANGBAND_LITE_MAC
2379 #else /* ANGBAND_LITE_MAC */
2382 case TERM_XTRA_SOUND:
2385 play_sound(v, sound_volume);
2391 #endif /* ANGBAND_LITE_MAC */
2393 /* Process random events */
2394 case TERM_XTRA_BORED:
2396 /* Process an event */
2397 (void)CheckEvents(FALSE);
2403 /* Process pending events */
2404 case TERM_XTRA_EVENT:
2406 /* Process an event */
2407 (void)CheckEvents(v);
2413 /* Flush all pending events (if any) */
2414 case TERM_XTRA_FLUSH:
2416 /* Hack -- flush all events */
2417 while (CheckEvents(TRUE)) /* loop */;
2423 /* Hack -- Change the "soft level" */
2424 case TERM_XTRA_LEVEL:
2426 /* Activate if requested */
2427 if (v) activate(td->w);
2433 /* Clear the screen */
2434 case TERM_XTRA_CLEAR:
2438 #if TARGET_API_MAC_CARBON
2439 GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &portRect );
2440 global_to_local( &portRect );
2442 portRect = td->w->portRect;
2445 /* No clipping XXX XXX XXX */
2446 ClipRect(&portRect);
2448 /* Erase the window */
2449 EraseRect(&portRect);
2452 term_data_color(td, TERM_WHITE);
2454 /* Frame the window in white */
2456 LineTo(0, td->size_hgt-1);
2457 LineTo(td->size_wid-1, td->size_hgt-1);
2458 LineTo(td->size_wid-1, 0);
2460 /* Clip to the new size */
2461 r.left = portRect.left + td->size_ow1;
2462 r.top = portRect.top + td->size_oh1;
2463 r.right = portRect.right - td->size_ow2;
2464 r.bottom = portRect.bottom - td->size_oh2;
2471 /* React to changes */
2472 case TERM_XTRA_REACT:
2474 /* React to changes */
2475 return (Term_xtra_mac_react());
2478 /* Delay (milliseconds) */
2479 case TERM_XTRA_DELAY:
2484 #if TARGET_API_MAC_CARBON
2488 /* Convert millisecs to ticks */
2489 ticks = (v * 60L) / 1000;
2492 * Hack? - Put the programme into sleep.
2493 * No events match ~everyEvent, so nothing
2494 * should be lost in Angband's event queue.
2495 * Even if ticks are 0, it's worth calling for
2496 * the above mentioned reasons.
2498 WaitNextEvent((EventMask)~everyEvent, &tmp, ticks, nil);
2500 long m = TickCount() + (v * 60L) / 1000;
2503 while (TickCount() < m) /* loop */;
2519 * Low level graphics (Assumes valid input).
2520 * Draw a "cursor" at (x,y), using a "yellow box".
2521 * We are allowed to use "Term_grab()" to determine
2522 * the current screen contents (for inverting, etc).
2524 static errr Term_curs_mac(int x, int y)
2528 term_data *td = (term_data*)(Term->data);
2531 term_data_color(td, TERM_YELLOW);
2533 /* Frame the grid */
2534 r.left = x * td->tile_wid + td->size_ow1;
2535 r.right = r.left + td->tile_wid;
2536 r.top = y * td->tile_hgt + td->size_oh1;
2537 r.bottom = r.top + td->tile_hgt;
2547 * Low level graphics (Assumes valid input).
2548 * Draw a "big cursor" at (x,y), using a "yellow box".
2549 * We are allowed to use "Term_grab()" to determine
2550 * the current screen contents (for inverting, etc).
2552 static errr Term_bigcurs_mac(int x, int y)
2556 term_data *td = (term_data*)(Term->data);
2559 term_data_color(td, TERM_YELLOW);
2561 /* Frame the grid */
2562 r.left = x * td->tile_wid + td->size_ow1;
2563 r.right = r.left + 2 * td->tile_wid;
2564 r.top = y * td->tile_hgt + td->size_oh1;
2565 r.bottom = r.top + td->tile_hgt;
2575 * Low level graphics (Assumes valid input)
2577 * Erase "n" characters starting at (x,y)
2579 static errr Term_wipe_mac(int x, int y, int n)
2583 term_data *td = (term_data*)(Term->data);
2585 /* Erase the block of characters */
2586 r.left = x * td->tile_wid + td->size_ow1;
2587 r.right = r.left + n * td->tile_wid;
2588 r.top = y * td->tile_hgt + td->size_oh1;
2589 r.bottom = r.top + td->tile_hgt;
2598 * Low level graphics. Assumes valid input.
2600 * Draw several ("n") chars, with an attr, at a given location.
2602 static errr Term_text_mac(int x, int y, int n, byte a, const char *cp)
2606 term_data *td = (term_data*)(Term->data);
2609 term_data_color(td, (a & 0x0F));
2611 /* Starting pixel */
2612 xp = x * td->tile_wid + td->tile_o_x + td->size_ow1;
2613 yp = y * td->tile_hgt + td->tile_o_y + td->size_oh1;
2615 /* Move to the correct location */
2618 /* Draw the character */
2619 if (n == 1) DrawChar(*cp);
2621 /* Draw the string */
2622 else DrawText(cp, 0, n);
2630 * Low level graphics (Assumes valid input)
2632 * Erase "n" characters starting at (x,y)
2634 static errr Term_pict_mac(int x, int y, int n, const byte *ap, const char *cp,
2635 const byte *tap, const char *tcp)
2639 term_data *td = (term_data*)(Term->data);
2640 GDHandle saveGDevice;
2641 GWorldPtr saveGWorld;
2644 GetGWorld(&saveGWorld, &saveGDevice);
2646 r2.left = x * td->tile_wid + td->size_ow1;
2647 r2.right = r2.left + td->tile_wid;
2648 r2.top = y * td->tile_hgt + td->size_oh1;
2649 r2.bottom = r2.top + td->tile_hgt;
2653 /* Instantiate font */
2654 TextFont(td->font_id);
2655 TextSize(td->font_size);
2656 TextFace(td->font_face);
2658 /* Restore colors */
2659 BackColor(blackColor);
2660 ForeColor(whiteColor);
2664 /* Destination rectangle */
2665 /* r2.left = x * td->tile_wid + td->size_ow1;
2666 r2.top = y * td->tile_hgt + td->size_oh1;
2667 r2.bottom = r2.top + td->tile_hgt;*/
2671 /* Scan the input */
2672 for (i = 0; i < n; i++)
2679 /* Second byte of bigtile */
2680 if (use_bigtile && a == 255)
2683 r2.left += td->tile_wid;
2688 /* Prepare right of rectangle now */
2689 r2.right = r2.left + td->tile_wid;
2691 #ifdef ANGBAND_LITE_MAC
2695 #else /* ANGBAND_LITE_MAC */
2697 /* Graphics -- if Available and Needed */
2698 if (use_graphics && ((byte)a & 0x80) && ((byte)c & 0x80))
2700 #if TARGET_API_MAC_CARBON
2701 PixMapHandle srcBitMap = GetGWorldPixMap(frameP->framePort);
2702 PixMapHandle destBitMap;
2704 BitMapPtr srcBitMap = (BitMapPtr)(frameP->framePix);
2705 BitMapPtr destBitMap;
2712 bool terrain_flag = FALSE;
2716 if ((a != ta || c != tc) &&
2717 ((byte)ta & 0x80) && ((byte)tc & 0x80))
2720 row = ((byte)ta & 0x7F);
2721 col = ((byte)tc & 0x7F);
2723 /* Terrain Source rectangle */
2724 terrain_r.left = col * grafWidth;
2725 terrain_r.top = row * grafHeight;
2726 terrain_r.right = terrain_r.left + grafWidth;
2727 terrain_r.bottom = terrain_r.top + grafHeight;
2729 terrain_flag = TRUE;
2733 row = ((byte)a & 0x7F);
2734 col = ((byte)c & 0x7F);
2736 /* Source rectangle */
2737 r1.left = col * grafWidth;
2738 r1.top = row * grafHeight;
2739 r1.right = r1.left + grafWidth;
2740 r1.bottom = r1.top + grafHeight;
2742 /* Hardwire CopyBits */
2743 BackColor(whiteColor);
2744 ForeColor(blackColor);
2746 /* Draw the picture */
2747 #if TARGET_API_MAC_CARBON
2748 destBitMap = GetPortPixMap(GetWindowPort( td->w ));
2750 destBitMap = (BitMapPtr)&(td->w->portBits);
2752 if (use_bigtile) r2.right += td->tile_wid;
2757 * Source mode const = srcCopy:
2759 * determine how close the color of the source
2760 * pixel is to black, and assign this relative
2761 * amount of foreground color to the
2762 * destination pixel; determine how close the
2763 * color of the source pixel is to white, and
2764 * assign this relative amount of background
2765 * color to the destination pixel
2767 #if TARGET_API_MAC_CARBON
2768 CopyBits( (BitMap *) *srcBitMap, (BitMap *) *destBitMap, &terrain_r, &r2, srcCopy, NULL);
2770 CopyBits( srcBitMap, destBitMap, &terrain_r, &r2, srcCopy, NULL );
2773 * Draw transparent tile
2774 * BackColor is ignored and the destination is
2777 BackColor(blackColor);
2778 #if TARGET_API_MAC_CARBON
2779 CopyBits( (BitMap *) *srcBitMap, (BitMap *) *destBitMap, &r1, &r2, transparent, NULL);
2781 CopyBits( srcBitMap, destBitMap, &r1, &r2, transparent, NULL );
2786 #if TARGET_API_MAC_CARBON
2787 CopyBits( (BitMap *) *srcBitMap, (BitMap *) *destBitMap, &r1, &r2, srcCopy, NULL);
2789 CopyBits( srcBitMap, destBitMap, &r1, &r2, srcCopy, NULL );
2793 /* Restore colors */
2794 BackColor(blackColor);
2795 ForeColor(whiteColor);
2804 #endif /* ANGBAND_LITE_MAC */
2812 term_data_color(td, (a & 0x0F));
2814 /* Starting pixel */
2815 xp = r2.left + td->tile_o_x;
2816 yp = r2.top + td->tile_o_y;
2818 /* Move to the correct location */
2824 /* Double width rectangle */
2825 r2.right += td->tile_wid;
2830 /* Draw the character */
2835 r2.left += td->tile_wid;
2843 /* Draw the character */
2849 r2.left += td->tile_wid;
2858 * Create and initialize window number "i"
2860 static void term_data_link(int i)
2864 term_data *td = &data[i];
2869 /* Require mapped */
2870 if (!td->mapped) return;
2875 /* Initialize the term */
2876 term_init(td->t, td->cols, td->rows, td->keys);
2878 /* Use a "software" cursor */
2879 td->t->soft_cursor = TRUE;
2881 /* Erase with "white space" */
2882 td->t->attr_blank = TERM_WHITE;
2883 td->t->char_blank = ' ';
2885 /* Prepare the init/nuke hooks */
2886 td->t->init_hook = Term_init_mac;
2887 td->t->nuke_hook = Term_nuke_mac;
2889 /* Prepare the function hooks */
2890 td->t->user_hook = Term_user_mac;
2891 td->t->xtra_hook = Term_xtra_mac;
2892 td->t->wipe_hook = Term_wipe_mac;
2893 td->t->curs_hook = Term_curs_mac;
2894 td->t->bigcurs_hook = Term_bigcurs_mac;
2895 td->t->text_hook = Term_text_mac;
2896 td->t->pict_hook = Term_pict_mac;
2898 /* Link the local structure */
2899 td->t->data = (vptr)(td);
2902 Term_activate(td->t);
2904 /* Global pointer */
2905 angband_term[i] = td->t;
2913 #ifdef MACH_O_CARBON
2917 * Return a POSIX pathname of the lib directory, or NULL if it can't be
2918 * located. Caller must supply a buffer along with its size in bytes,
2919 * where returned pathname will be stored.
2920 * I prefer use of goto's to several nested if's, if they involve error
2921 * handling. Sorry if you are offended by their presence. Modern
2922 * languages have neater constructs for this kind of jobs -- pelpel
2924 static char *locate_lib(char *buf, size_t size)
2926 CFURLRef main_url = NULL;
2927 CFStringRef main_str = NULL;
2931 /* Obtain the URL of the main bundle */
2932 main_url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
2935 if (main_url == NULL) goto ret;
2937 /* Convert it to POSIX pathname */
2938 main_str = CFURLCopyFileSystemPath(main_url, kCFURLPOSIXPathStyle);
2941 if (main_str == NULL) goto ret;
2943 /* Convert it again from darn unisomething encoding to ASCII */
2944 if (CFStringGetCString(main_str, buf, size, kTextEncodingUS_ASCII) == FALSE)
2947 /* Find the last '/' in the pathname */
2948 p = strrchr(buf, '/');
2950 /* Paranoia - cannot happen */
2951 if (p == NULL) goto ret;
2953 /* Remove the trailing path */
2957 * Paranoia - bounds check, with 5 being the length of "/lib/"
2958 * and 1 for terminating '\0'.
2960 if (strlen(buf) + 5 + 1 > size) goto ret;
2962 /* Append "/lib/" */
2963 strcat(buf, "/lib/");
2970 /* Release objects allocated and implicitly retained by the program */
2971 if (main_str) CFRelease(main_str);
2972 if (main_url) CFRelease(main_url);
2974 /* pathname of the lib folder or NULL */
2979 #else /* MACH_O_CARBON */
2983 * Set the "current working directory" (also known as the "default"
2984 * volume/directory) to the location of the current application.
2986 * Code by: Maarten Hazewinkel (mmhazewi@cs.ruu.nl)
2988 * This function does not appear to work correctly with System 6.
2990 static void SetupAppDir(void)
2994 char errString[100];
2996 /* Get the location of the Angband executable */
2997 fcbBlock.ioCompletion = NULL;
2998 fcbBlock.ioNamePtr = NULL;
2999 fcbBlock.ioVRefNum = 0;
3000 fcbBlock.ioRefNum = CurResFile();
3001 fcbBlock.ioFCBIndx = 0;
3002 err = PBGetFCBInfo(&fcbBlock, FALSE);
3006 sprintf(errString, "PBGetFCBInfo ¥¨¥é¡¼ #%d.\r ½ªÎ»¤·¤Þ¤¹.", err);
3008 sprintf(errString, "Fatal PBGetFCBInfo Error #%d.\r Exiting.", err);
3010 mac_warning(errString);
3014 /* Extract the Vol and Dir */
3015 app_vol = fcbBlock.ioFCBVRefNum;
3016 app_dir = fcbBlock.ioFCBParID;
3018 /* Set the current working directory to that location */
3019 err = HSetVol(NULL, app_vol, app_dir);
3023 sprintf(errString, "HSetVol ¥¨¥é¡¼ #%d.\r ½ªÎ»¤·¤Þ¤¹.", err);
3025 sprintf(errString, "Fatal HSetVol Error #%d.\r Exiting.", err);
3027 mac_warning(errString);
3036 #if TARGET_API_MAC_CARBON
3038 * Using Core Foundation's Preferences services -- pelpel
3040 * Requires OS 8.6 or greater with CarbonLib 1.1 or greater. Or OS X,
3043 * Without this, we can support older versions of OS 8 as well
3044 * (with CarbonLib 1.0.4).
3046 * Frequent allocation/deallocation of small chunks of data is
3047 * far from my liking, but since this is only called at the
3048 * beginning and the end of a session, I hope this hardly matters.
3053 * Store "value" as the value for preferences item name
3056 static void save_pref_short(const char *key, short value)
3059 CFNumberRef cf_value;
3061 /* allocate and initialise the key */
3062 cf_key = CFStringCreateWithCString(NULL, key, kTextEncodingUS_ASCII);
3064 /* allocate and initialise the value */
3065 cf_value = CFNumberCreate(NULL, kCFNumberShortType, &value);
3067 if ((cf_key != NULL) && (cf_value != NULL))
3069 /* Store the key-value pair in the applications preferences */
3070 CFPreferencesSetAppValue(
3073 kCFPreferencesCurrentApplication);
3077 * Free CF data - the reverse order is a vain attempt to
3078 * minimise memory fragmentation.
3080 if (cf_value) CFRelease(cf_value);
3081 if (cf_key) CFRelease(cf_key);
3086 * Load preference value for key, returns TRUE if it succeeds with
3087 * vptr updated appropriately, FALSE otherwise.
3089 static bool query_load_pref_short(const char *key, short *vptr)
3092 CFNumberRef cf_value;
3094 /* allocate and initialise the key */
3095 cf_key = CFStringCreateWithCString(NULL, key, kTextEncodingUS_ASCII);
3098 if (cf_key == NULL) return (FALSE);
3100 /* Retrieve value for the key */
3101 cf_value = CFPreferencesCopyAppValue(
3103 kCFPreferencesCurrentApplication);
3105 /* Value not found */
3106 if (cf_value == NULL)
3112 /* Convert the value to short */
3119 CFRelease(cf_value);
3128 * Update short data pointed by vptr only if preferences
3129 * value for key is located.
3131 static void load_pref_short(const char *key, short *vptr)
3135 if (query_load_pref_short(key, &tmp)) *vptr = tmp;
3141 * Save preferences to preferences file for current host+current user+
3142 * current application.
3144 static void cf_save_prefs()
3149 save_pref_short("version.major", FAKE_VERSION);
3150 save_pref_short("version.minor", FAKE_VER_MAJOR);
3151 save_pref_short("version.patch", FAKE_VER_MINOR);
3152 save_pref_short("version.extra", FAKE_VER_PATCH);
3155 save_pref_short("arg.arg_sound", arg_sound);
3156 save_pref_short("arg.arg_graphics", arg_graphics);
3157 save_pref_short("arg.arg_newstyle_graphics", arg_newstyle_graphics);
3158 save_pref_short("arg.arg_bigtile", arg_bigtile);
3160 #ifndef MACH_O_CARBON
3163 for( i = 0 ; i < 7 ; i++ )
3164 save_pref_short(format("sound%d.on", i), soundmode[i]);
3166 #endif /* MACH_O_CARBON */
3169 for (i = 0; i < MAX_TERM_DATA; i++)
3171 term_data *td = &data[i];
3173 save_pref_short(format("term%d.mapped", i), td->mapped);
3175 save_pref_short(format("term%d.font_id", i), td->font_id);
3176 save_pref_short(format("term%d.font_size", i), td->font_size);
3177 save_pref_short(format("term%d.font_face", i), td->font_face);
3179 save_pref_short(format("term%d.tile_wid", i), td->tile_wid);
3180 save_pref_short(format("term%d.tile_hgt", i), td->tile_hgt);
3182 save_pref_short(format("term%d.cols", i), td->cols);
3183 save_pref_short(format("term%d.rows", i), td->rows);
3184 save_pref_short(format("term%d.left", i), td->r.left);
3185 save_pref_short(format("term%d.top", i), td->r.top);
3189 * Make sure preferences are persistent
3191 CFPreferencesAppSynchronize(
3192 kCFPreferencesCurrentApplication);
3197 * Load preferences from preferences file for current host+current user+
3198 * current application.
3200 static void cf_load_prefs()
3203 short pref_major, pref_minor, pref_patch, pref_extra;
3208 /* Assume nothing is wrong, yet */
3211 /* Load version information */
3212 ok &= query_load_pref_short("version.major", &pref_major);
3213 ok &= query_load_pref_short("version.minor", &pref_minor);
3214 ok &= query_load_pref_short("version.patch", &pref_patch);
3215 ok &= query_load_pref_short("version.extra", &pref_extra);
3217 /* Any of the above failed */
3220 /* This may be the first run */
3222 mac_warning("½é´üÀßÄê¥Õ¥¡¥¤¥ë¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó¡£");
3224 mac_warning("Preferences are not found.");
3227 /* Ignore the rest */
3234 if ((pref_major != PREF_VER_MAJOR) ||
3235 (pref_minor != PREF_VER_MINOR) ||
3236 (pref_patch != PREF_VER_PATCH) ||
3237 (pref_extra != PREF_VER_EXTRA))
3241 format("Ignoring %d.%d.%d.%d preferences.",
3242 pref_major, pref_minor, pref_patch, pref_extra));
3255 if (query_load_pref_short("arg.arg_sound", &pref_tmp))
3256 arg_sound = pref_tmp;
3259 if (query_load_pref_short("arg.arg_graphics", &pref_tmp))
3260 arg_graphics = pref_tmp;
3262 /*newstyle graphics*/
3263 if (query_load_pref_short("arg.arg_newstyle_graphics", &pref_tmp))
3265 use_newstyle_graphics = pref_tmp;
3268 if (use_newstyle_graphics == true)
3270 ANGBAND_GRAF = "new";
3271 arg_newstyle_graphics = true;
3272 grafWidth = grafHeight = 16;
3277 ANGBAND_GRAF = "old";
3278 arg_newstyle_graphics = false;
3279 grafWidth = grafHeight = 8;
3283 /* double-width tiles */
3284 if (query_load_pref_short("arg.arg_bigtile", &pref_tmp))
3286 use_bigtile = pref_tmp;
3291 #ifndef MACH_O_CARBON
3294 for( i = 0 ; i < 7 ; i++ )
3296 query_load_pref_short(format("sound%d.on", i), &soundmode[i]);
3299 #endif /* MACH_O_CARBON */
3302 m = GetMenuHandle(134);
3304 /* Item "arg_sound" */
3305 CheckMenuItem(m, 1, arg_sound);
3307 /* Item "arg_graphics" */
3308 CheckMenuItem(m, 2, arg_graphics);
3310 /* Item "arg_newstyle_graphics"*/
3311 CheckMenuItem(m, 8, arg_newstyle_graphics);
3313 /* Item "arg_bigtile"*/
3314 CheckMenuItem(m, 9, arg_bigtile);
3317 for (i = 0; i < MAX_TERM_DATA; i++)
3319 term_data *td = &data[i];
3321 load_pref_short(format("term%d.mapped", i), &td->mapped);
3323 load_pref_short(format("term%d.font_id", i), &td->font_id);
3324 load_pref_short(format("term%d.font_size", i), &td->font_size);
3325 load_pref_short(format("term%d.font_face", i), &td->font_face);
3327 load_pref_short(format("term%d.tile_wid", i), &td->tile_wid);
3328 load_pref_short(format("term%d.tile_hgt", i), &td->tile_hgt);
3330 load_pref_short(format("term%d.cols", i), &td->cols);
3331 load_pref_short(format("term%d.rows", i), &td->rows);
3332 load_pref_short(format("term%d.left", i), &td->r.left);
3333 load_pref_short(format("term%d.top", i), &td->r.top);
3339 * Global "preference" file pointer
3344 * Read a "short" from the file
3346 static int getshort(void)
3350 if (0 == my_fgets(fff, buf, sizeof(buf))) x = atoi(buf);
3355 * Dump a "short" to the file
3357 static void putshort(int x)
3359 fprintf(fff, "%d\n", x);
3365 * Write the "preference" data to the current "file"
3367 static void save_prefs(void)
3374 /*** The current version ***/
3376 putshort(FAKE_VERSION);
3377 putshort(FAKE_VER_MAJOR);
3378 putshort(FAKE_VER_MINOR);
3379 putshort(FAKE_VER_PATCH);
3381 putshort(arg_sound);
3382 putshort(arg_graphics);
3383 putshort(arg_newstyle_graphics);
3384 putshort(arg_bigtile);
3387 for( i = 0 ; i < 7 ; i++ )
3388 putshort(soundmode[i]);
3391 for (i = 0; i < MAX_TERM_DATA; i++)
3396 putshort(td->mapped);
3398 putshort(td->font_id);
3399 putshort(td->font_size);
3400 putshort(td->font_face);
3402 putshort(td->tile_wid);
3403 putshort(td->tile_hgt);
3408 putshort(td->r.left);
3409 putshort(td->r.top);
3415 * Load the preferences from the current "file"
3417 * XXX XXX XXX Being able to undefine various windows is
3418 * slightly bizarre, and may cause problems.
3420 static void load_prefs(void)
3424 int old_version, old_major, old_minor, old_patch;
3429 /*** Version information ***/
3431 /* Preferences version */
3432 old_version = getshort();
3433 old_major = getshort();
3434 old_minor = getshort();
3435 old_patch = getshort();
3437 /* Hack -- Verify or ignore */
3438 if ((old_version != FAKE_VERSION) ||
3439 (old_major != FAKE_VER_MAJOR) ||
3440 (old_minor != FAKE_VER_MINOR) ||
3441 (old_patch != FAKE_VER_PATCH))
3445 mac_warning("¸Å¤¤½é´üÀßÄê¥Õ¥¡¥¤¥ë¤ò̵»ë¤·¤Þ¤¹.");
3447 mac_warning("Ignoring old preferences.");
3453 arg_sound = getshort();
3454 arg_graphics = getshort();
3455 arg_newstyle_graphics = getshort();
3456 use_newstyle_graphics = arg_newstyle_graphics;
3458 if (use_newstyle_graphics == true)
3460 ANGBAND_GRAF = "new";
3461 arg_newstyle_graphics = true;
3462 grafWidth = grafHeight = 16;
3467 ANGBAND_GRAF = "old";
3468 arg_newstyle_graphics = false;
3469 grafWidth = grafHeight = 8;
3473 arg_bigtile = getshort();
3474 use_bigtile = arg_bigtile;
3477 for( i = 0 ; i < 7 ; i++ )
3478 soundmode[i] = getshort();
3481 m = GetMenuHandle(134);
3483 /* Item "arg_sound" */
3484 CheckItem(m, 1, arg_sound);
3486 /* Item "arg_graphics" */
3487 CheckItem(m, 2, arg_graphics);
3489 /* Item "arg_newstyle_graphics"*/
3490 CheckItem(m, 8, arg_newstyle_graphics);
3492 /* Item "arg_bigtile"*/
3493 CheckItem(m, 9, arg_bigtile);
3496 for (i = 0; i < MAX_TERM_DATA; i++)
3501 td->mapped = getshort();
3503 td->font_id = getshort();
3504 td->font_size = getshort();
3505 td->font_face = getshort();
3507 td->tile_wid = getshort();
3508 td->tile_hgt = getshort();
3510 td->cols = getshort();
3511 td->rows = getshort();
3513 td->r.left = getshort();
3514 td->r.top = getshort();
3517 if (feof(fff)) break;
3520 #endif /* TARGET_API_MAC_CARBON */
3525 * Hack -- default data for a window
3527 static void term_data_hack(term_data *td)
3531 #if TARGET_API_MAC_CARBON
3533 /* Default to Osaka font (Japanese) */
3534 fid = FMGetFontFamilyFromName( "\pOsaka¡ÝÅùÉý" );
3536 /* Default to Monaco font */
3537 fid = FMGetFontFamilyFromName("\pmonaco");
3541 /* Default to ÅùÉýÌÀÄ« font (Japanese) */
3542 GetFNum( "\pÅùÉýÌÀÄ«", &fid);
3543 SetFScaleDisable( true );
3545 /* Default to Monaco font */
3546 GetFNum("\pmonaco", &fid);
3551 WIPE(td, term_data);
3556 /* Default borders */
3567 /* Default font size */
3570 /* Default font face */
3577 /* Default position */
3587 * Read the preference file, Create the windows.
3589 * We attempt to use "FindFolder()" to track down the preference file,
3590 * but if this fails, for any reason, we will try the "SysEnvirons()"
3591 * method, which may work better with System 6.
3593 static void init_windows(void)
3599 #if !TARGET_API_MAC_CARBON
3607 #endif /* !TARGET_API_MAC_CARBON */
3610 /*** Default values ***/
3612 /* Initialize (backwards) */
3613 for (i = MAX_TERM_DATA - 1; i >= 0; i--)
3626 s = angband_term_name[i];
3631 /* Maximal length */
3634 /* Copy the title */
3635 strncpy((char*)(td->title) + 1, s, n);
3637 /* Save the length */
3640 /* Tile the windows */
3641 td->r.left += (b * 30);
3642 td->r.top += (b * 30);
3649 /*** Load preferences ***/
3651 #if TARGET_API_MAC_CARBON
3654 /* Assume failure */
3657 /* Assume failure */
3670 /* Find the folder */
3671 err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
3677 /* Extract a path name */
3678 PathNameFromDirID(dirID, vref, (StringPtr)foo);
3680 /* Convert the string */
3681 ptocstr((StringPtr)foo);
3683 /* Append the preference file name */
3684 strcat(foo, PREF_FILE_NAME);
3686 /* Open the preference file */
3687 fff = fopen(foo, "r");
3694 #endif /* USE_SFL_CODE */
3700 HGetVol(0, &savev, &saved);
3702 /* Go to the "system" folder */
3703 SysEnvirons(curSysEnvVers, &env);
3704 SetVol(0, env.sysVRefNum);
3707 fff = fopen(PREF_FILE_NAME, "r");
3710 HSetVol(0, savev, saved);
3713 /* Load preferences */
3716 /* Load a real preference file */
3719 /* Close the file */
3722 #endif /* TARGET_API_MAC_CARBON */
3725 /*** Instantiate ***/
3736 /* Link (backwards, for stacking order) */
3737 for (i = MAX_TERM_DATA - 1; i >= 0; i--)
3746 Term_activate(td->t);
3749 #ifndef MACH_O_CARBON
3751 static void init_sound( void )
3755 SignedByte permission = fsRdPerm;
3761 /* Descend into "lib" folder */
3762 pb.dirInfo.ioCompletion = NULL;
3763 pb.dirInfo.ioNamePtr = "\plib";
3764 pb.dirInfo.ioVRefNum = app_vol;
3765 pb.dirInfo.ioDrDirID = app_dir;
3766 pb.dirInfo.ioFDirIndex = 0;
3768 /* Check for errors */
3769 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3772 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3774 /* Descend into "lib/save" folder */
3775 pb.dirInfo.ioCompletion = NULL;
3776 pb.dirInfo.ioNamePtr = "\pxtra";
3777 pb.dirInfo.ioVRefNum = app_vol;
3778 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3779 pb.dirInfo.ioFDirIndex = 0;
3781 /* Check for errors */
3782 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3785 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3787 /* Descend into "lib/save" folder */
3788 pb.dirInfo.ioCompletion = NULL;
3789 pb.dirInfo.ioNamePtr = "\psound";
3790 pb.dirInfo.ioVRefNum = app_vol;
3791 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3792 pb.dirInfo.ioFDirIndex = 0;
3794 /* Check for errors */
3795 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3798 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3800 ret = HOpenResFile( app_vol , pb.dirInfo.ioDrDirID , "\psound.rsrc" , permission );
3804 for( i = 0 ; i < 7 ; i++ )
3805 soundmode[i] = false;
3807 for( i = 1 ; i < SOUND_MAX ; i++ ){
3808 /* Get the proper sound name */
3809 sprintf((char*)sound + 1, "%.16s.wav", angband_sound_name[i]);
3810 sound[0] = strlen((char*)sound + 1);
3812 /* Obtain resource XXX XXX XXX */
3813 handle = Get1NamedResource('snd ', sound);
3814 if( handle == NULL || ext_sound )
3815 handle = GetNamedResource('snd ', sound);
3818 soundmode[soundchoice[i]] = true;
3827 static void init_graf( void )
3831 SignedByte permission = fsRdPerm;
3837 /* Descend into "lib" folder */
3838 pb.dirInfo.ioCompletion = NULL;
3839 pb.dirInfo.ioNamePtr = "\plib";
3840 pb.dirInfo.ioVRefNum = app_vol;
3841 pb.dirInfo.ioDrDirID = app_dir;
3842 pb.dirInfo.ioFDirIndex = 0;
3844 /* Check for errors */
3845 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3848 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3850 /* Descend into "lib/xtra" folder */
3851 pb.dirInfo.ioCompletion = NULL;
3852 pb.dirInfo.ioNamePtr = "\pxtra";
3853 pb.dirInfo.ioVRefNum = app_vol;
3854 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3855 pb.dirInfo.ioFDirIndex = 0;
3857 /* Check for errors */
3858 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3861 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3863 /* Descend into "lib/xtra/graf" folder */
3864 pb.dirInfo.ioCompletion = NULL;
3865 pb.dirInfo.ioNamePtr = "\pgraf";
3866 pb.dirInfo.ioVRefNum = app_vol;
3867 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3868 pb.dirInfo.ioFDirIndex = 0;
3870 /* Check for errors */
3871 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3874 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3876 ret = HOpenResFile( app_vol , pb.dirInfo.ioDrDirID , "\pgraf.rsrc" , permission );
3881 /* Obtain resource XXX XXX XXX */
3882 handle = Get1NamedResource('PICT', graf);
3883 if ( handle == NULL || ext_graf )
3884 handle = GetNamedResource('PICT', "\pgraf.rsrc");
3891 #endif /* MACH_O_CARBON */
3897 static void init_chuukei( void )
3903 path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "chuukei.txt");
3905 fp = fopen(path, "r");
3910 if (fgets(tmp, 1024, fp)){
3912 int n = strlen(tmp);
3918 chuukei_server = TRUE;
3919 if(connect_chuukei_server(&tmp[2])<0){
3920 msg_print("connect fail");
3923 msg_print("connect");
3930 chuukei_client = TRUE;
3931 connect_chuukei_server(&tmp[2]);
3947 short InevrtCheck( DialogPtr targetDlg, short check )
3954 GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
3955 result = (GetControlValue( (ControlHandle)checkH ) + 1 ) % 2;
3956 SetControlValue( (ControlHandle)checkH , result );
3964 short SetCheck( DialogPtr targetDlg, short check, long result )
3971 GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
3972 SetControlValue( (ControlHandle)checkH , result );
3980 short GetCheck( DialogPtr targetDlg, short check )
3987 GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
3988 result = GetControlValue( (ControlHandle)checkH );
3992 void SoundConfigDLog(void)
3998 dialog=GetNewDialog(131, 0, (WindowPtr)-1);
3999 SetDialogDefaultItem( dialog, ok );
4000 SetDialogCancelItem( dialog, cancel );
4001 for( i = 1 ; i < 7 ; i++ )
4002 SetCheck( dialog, i+2 , soundmode[i] );
4004 /* ShowWindow(dialog); */
4005 for( item_hit = 100 ; cancel < item_hit ; ){
4006 ModalDialog(0, &item_hit);
4010 for( i = 1 ; i < 7 ; i++ )
4011 soundmode[i] = GetCheck( dialog, i+2 );
4016 InevrtCheck( dialog, item_hit );
4019 DisposeDialog(dialog);
4027 #if TARGET_API_MAC_CARBON
4028 static void save_pref_file(void)
4033 static void save_pref_file(void)
4042 /* Assume failure */
4045 /* Assume failure */
4062 /* Find the folder */
4063 err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
4069 /* Extract a path name */
4070 PathNameFromDirID(dirID, vref, (StringPtr)foo);
4072 /* Convert the string */
4073 ptocstr((StringPtr)foo);
4075 /* Append the preference file name */
4076 strcat(foo, PREF_FILE_NAME);
4078 /* Open the preference file */
4079 /* my_fopen set file type and file creator for MPW */
4080 fff = my_fopen(foo, "w");
4087 #endif /* USE_SFL_CODE */
4093 HGetVol(0, &savev, &saved);
4095 /* Go to "system" folder */
4096 SysEnvirons(curSysEnvVers, &env);
4097 SetVol(0, env.sysVRefNum);
4099 /* Open the preference file */
4100 /* my_fopen set file type and file creator for MPW */
4101 fff = fopen(PREF_FILE_NAME, "w");
4104 HSetVol(0, savev, saved);
4107 /* Save preferences */
4110 /* Write the preferences */
4121 #if defined(__MWERKS__)
4124 * A simple "Yes/No" filter to parse "key press" events in dialog windows
4126 static pascal Boolean ynfilter(DialogPtr dialog, EventRecord *event, short *ip)
4128 /* Parse key press events */
4129 if (event->what == keyDown)
4134 /* Extract the pressed key */
4135 c = (event->message & charCodeMask);
4137 /* Accept "no" and <return> and <enter> */
4138 if ((c=='n') || (c=='N') || (c==13) || (c==3)) i = 1;
4141 else if ((c=='y') || (c=='Y')) i = 2;
4143 /* Handle "yes" or "no" */
4147 ControlHandle control;
4150 /* Get the button */
4151 GetDialogItem(dialog, i, &type, (Handle*)&control, &r);
4153 /* Blink button for 1/10 second */
4154 HiliteControl(control, 1);
4155 Term_xtra_mac(TERM_XTRA_DELAY, 100);
4156 HiliteControl(control, 0);
4168 #endif /* __MWERKS__ */
4171 #if TARGET_API_MAC_CARBON
4174 * Prepare savefile dialogue and set the variable
4175 * savefile accordingly. Returns true if it succeeds, false (or
4176 * aborts) otherwise. If all is false, only allow files whose type
4178 * Originally written by Peter Ammon
4180 static bool select_savefile(bool all)
4183 FSSpec theFolderSpec;
4184 FSSpec savedGameSpec;
4185 NavDialogOptions dialogOptions;
4186 NavReplyRecord reply;
4187 /* Used only when 'all' is true */
4188 NavTypeList types = {ANGBAND_CREATOR, 1, 1, {'SAVE'}};
4189 NavTypeListHandle myTypeList;
4190 AEDesc defaultLocation;
4192 #ifdef MACH_O_CARBON
4194 /* Find the save folder */
4195 err = path_to_spec(ANGBAND_DIR_SAVE, &theFolderSpec);
4199 /* Find :lib:save: folder */
4200 err = FSMakeFSSpec(app_vol, app_dir, "\p:lib:save:", &theFolderSpec);
4205 if (err != noErr) quit("Unable to find the folder :lib:save:");
4207 /* Get default Navigator dialog options */
4208 err = NavGetDefaultDialogOptions(&dialogOptions);
4210 /* Clear preview option */
4211 dialogOptions.dialogOptionFlags &= ~kNavAllowPreviews;
4213 /* Disable multiple file selection */
4214 dialogOptions.dialogOptionFlags &= ~kNavAllowMultipleFiles;
4216 /* Make descriptor for default location */
4217 err = AECreateDesc(typeFSS, &theFolderSpec, sizeof(FSSpec),
4221 if (err != noErr) quit("Unable to allocate descriptor");
4223 /* We are indifferent to signature and file types */
4226 myTypeList = (NavTypeListHandle)nil;
4229 /* Set up type handle */
4232 err = PtrToHand(&types, (Handle *)&myTypeList, sizeof(NavTypeList));
4235 if (err != noErr) quit("Error in PtrToHand. Try enlarging heap");
4239 /* Call NavGetFile() with the types list */
4240 err = NavChooseFile(&defaultLocation, &reply, &dialogOptions, NULL,
4241 NULL, NULL, myTypeList, NULL);
4243 /* Free type list */
4244 if (!all) DisposeHandle((Handle)myTypeList);
4252 /* Invalid response -- allow the user to cancel */
4253 else if (!reply.validRecord)
4255 /* Hack -- Fake error */
4259 /* Retrieve FSSpec from the reply */
4262 AEKeyword theKeyword;
4263 DescType actualType;
4266 /* Get a pointer to selected file */
4267 (void)AEGetNthPtr(&reply.selection, 1, typeFSS, &theKeyword,
4268 &actualType, &savedGameSpec, sizeof(FSSpec), &actualSize);
4270 /* Dispose NavReplyRecord, resources and descriptors */
4271 (void)NavDisposeReply(&reply);
4274 /* Dispose location info */
4275 AEDisposeDesc(&defaultLocation);
4278 if (err != noErr) return (FALSE);
4280 #ifdef MACH_O_CARBON
4282 /* Convert FSSpec to pathname and store it in variable savefile */
4283 (void)spec_to_path(&savedGameSpec, savefile, sizeof(savefile));
4287 /* Convert FSSpec to pathname and store it in variable savefile */
4290 savedGameSpec.parID,
4291 savedGameSpec.vRefNum,
4292 (char *)savedGameSpec.name);
4303 * Handle menu: "File" + "New"
4305 static void do_menu_file_new(void)
4310 /* Game is in progress */
4311 game_in_progress = 1;
4325 * Handle menu: "File" + "Open"
4327 #if TARGET_API_MAC_CARBON
4328 static void do_menu_file_open(bool all)
4330 /* Let the player to choose savefile */
4331 if (!select_savefile(all)) return;
4336 /* Game is in progress */
4337 game_in_progress = TRUE;
4349 static void do_menu_file_open(bool all)
4363 /* vrefnum = GetSFCurVol(); */
4364 vrefnum = -*((short*)0x214);
4366 /* drefnum = GetSFCurDir(); */
4367 drefnum = *((long*)0x398);
4369 /* Descend into "lib" folder */
4370 pb.ioCompletion = NULL;
4371 pb.ioNamePtr = "\plib";
4372 pb.ioVRefNum = vrefnum;
4373 pb.ioDrDirID = drefnum;
4376 /* Check for errors */
4377 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
4380 if ((err == noErr) && (pb.ioFlAttrib & 0x10))
4382 /* Descend into "lib/save" folder */
4383 pb.ioCompletion = NULL;
4384 pb.ioNamePtr = "\psave";
4385 pb.ioVRefNum = vrefnum;
4386 pb.ioDrDirID = pb.ioDrDirID;
4389 /* Check for errors */
4390 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
4393 if ((err == noErr) && (pb.ioFlAttrib & 0x10))
4395 /* SetSFCurDir(pb.ioDrDirID); */
4396 *((long*)0x398) = pb.ioDrDirID;
4400 /* Window location */
4401 topleft.h = (qd.screenBits.bounds.left+qd.screenBits.bounds.right)/2-344/2;
4402 topleft.v = (2*qd.screenBits.bounds.top+qd.screenBits.bounds.bottom)/3-188/2;
4404 /* Allow "all" files */
4408 SFGetFile(topleft, "\p", NULL, -1, types, NULL, &reply);
4411 /* Allow "save" files */
4418 SFGetFile(topleft, "\p", NULL, 1, types, NULL, &reply);
4422 if (!reply.good) return;
4424 /* Extract textual file name for save file */
4425 GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
4426 refnum_to_name(savefile, drefnum, vrefnum, (char*)reply.fName);
4431 /* Game is in progress */
4432 game_in_progress = 1;
4447 * Handle the "open_when_ready" flag
4449 static void handle_open_when_ready(void)
4451 /* Check the flag XXX XXX XXX make a function for this */
4452 if (open_when_ready && initialized && !game_in_progress)
4455 open_when_ready = FALSE;
4457 /* Game is in progress */
4458 game_in_progress = 1;
4477 * Initialize the menus
4479 * Verify menus 128, 129, 130
4480 * Create menus 131, 132, 133, 134
4482 * The standard menus are:
4484 * Apple (128) = { About, -, ... }
4485 * File (129) = { New,Open,Import,Close,Save,-,Exit,Quit }
4486 * Edit (130) = { Cut, Copy, Paste, Clear } (?)
4487 * Font (131) = { Bold, Extend, -, Monaco, ..., -, ... }
4488 * Size (132) = { ... }
4489 * Window (133) = { Angband, Mirror, Recall, Choice,
4490 * Term-4, Term-5, Term-6, Term-7 }
4491 * Special (134) = { arg_sound, arg_graphics, -,
4492 * arg_fiddle, arg_wizard }
4494 static void init_menubar(void)
4506 /* Get the "apple" menu */
4509 /* Insert the menu */
4512 /* Add the DA's to the "apple" menu */
4513 #if TARGET_API_MAC_CARBON
4515 AppendResMenu (m, 'DRVR');
4518 /* Get the "File" menu */
4519 #if TARGET_API_MAC_CARBON
4521 err = Gestalt( gestaltSystemVersion, &response );
4522 if ( (err == noErr) && (response >= 0x00000A00) )
4524 DeleteMenuItem( m, 7 );
4530 /* Insert the menu */
4534 /* Get the "Edit" menu */
4537 /* Insert the menu */
4541 /* Make the "Font" menu */
4543 m = NewMenu(131, "\p¥Õ¥©¥ó¥È");
4545 m = NewMenu(131, "\pFont");
4548 /* Insert the menu */
4552 AppendMenu(m, "\pBold");
4555 AppendMenu(m, "\pWide");
4557 /* Add a separator */
4558 AppendMenu(m, "\p-");
4561 r.left = r.right = r.top = r.bottom = 0;
4563 /* Make the fake window */
4564 tmpw = NewWindow(0, &r, "\p", false, documentProc, 0, 0, 0);
4566 /* Activate the "fake" window */
4567 #if TARGET_API_MAC_CARBON
4568 SetPortWindowPort(tmpw);
4579 /* Add the fonts to the menu */
4580 AppendResMenu(m, 'FONT');
4583 #if TARGET_API_MAC_CARBON
4584 n = CountMenuItems(m);
4590 for (i = n; i >= 4; i--)
4595 /* Acquire the font name */
4596 GetMenuItemText(m, i, tmpName);
4598 /* Acquire the font index */
4599 #if TARGET_API_MAC_CARBON
4600 fontNum = FMGetFontFamilyFromName( tmpName );
4602 GetFNum(tmpName, &fontNum);
4605 /* Apply the font index */
4608 /* Remove non-mono-spaced fonts */
4609 if ((CharWidth('i') != CharWidth('W')) || (CharWidth('W') == 0))
4611 /* Delete the menu item XXX XXX XXX */
4612 DeleteMenuItem (m, i);
4616 /* Destroy the old window */
4617 DisposeWindow(tmpw);
4619 /* Add a separator */
4620 AppendMenu(m, "\p-");
4622 /* Add the fonts to the menu */
4623 AppendResMenu (m, 'FONT');
4626 /* Make the "Size" menu */
4628 m = NewMenu(132, "\p¥µ¥¤¥º");
4630 m = NewMenu(132, "\pSize");
4633 /* Insert the menu */
4636 /* Add some sizes (stagger choices) */
4637 for (i = 8; i <= 32; i += ((i / 16) + 1))
4642 sprintf((char*)buf + 1, "%d", i);
4643 buf[0] = strlen((char*)buf + 1);
4650 /* Make the "Windows" menu */
4652 m = NewMenu(133, "\p¥¦¥¤¥ó¥É¥¦");
4654 m = NewMenu(133, "\pWindows");
4657 /* Insert the menu */
4660 /* Default choices */
4661 for (i = 0; i < MAX_TERM_DATA; i++)
4665 /* Describe the item */
4666 sprintf((char*)buf + 1, "%.15s", angband_term_name[i]);
4667 buf[0] = strlen((char*)buf + 1);
4672 /* Command-Key shortcuts */
4673 if (i < 8) SetItemCmd(m, i + 1, '0' + i);
4677 /* Make the "Special" menu */
4679 m = NewMenu(134, "\pÆÃÊÌ");
4681 m = NewMenu(134, "\pSpecial");
4684 /* Insert the menu */
4687 /* Append the choices */
4689 AppendMenu(m, "\p¥µ¥¦¥ó¥É»ÈÍÑ");
4690 AppendMenu(m, "\p¥°¥é¥Õ¥£¥Ã¥¯»ÈÍÑ");
4691 AppendMenu(m, "\p-");
4692 AppendMenu(m, "\parg_fiddle");
4693 AppendMenu(m, "\parg_wizard");
4694 AppendMenu(m, "\p-");
4695 AppendMenu(m, "\p¥µ¥¦¥ó¥ÉÀßÄê...");
4696 AppendMenu(m, "\p16X16¥°¥é¥Õ¥£¥Ã¥¯");
4697 AppendMenu(m, "\p£²ÇÜÉý¥¿¥¤¥ëɽ¼¨");
4699 AppendMenu(m, "\parg_sound");
4700 AppendMenu(m, "\parg_graphics");
4701 AppendMenu(m, "\p-");
4702 AppendMenu(m, "\parg_fiddle");
4703 AppendMenu(m, "\parg_wizard");
4704 AppendMenu(m, "\p-");
4705 AppendMenu(m, "\pSound config");
4706 AppendMenu(m, "\pAdam Bolt tile");
4707 AppendMenu(m, "\pBigtile Mode");
4710 /* Make the "TileWidth" menu */
4712 m = NewMenu(135, "\p¥¿¥¤¥ëÉý");
4714 m = NewMenu(135, "\pTileWidth");
4717 /* Insert the menu */
4720 /* Add some sizes */
4721 for (i = 4; i <= 32; i++)
4726 sprintf((char*)buf + 1, "%d", i);
4727 buf[0] = strlen((char*)buf + 1);
4734 /* Make the "TileHeight" menu */
4736 m = NewMenu(136, "\p¥¿¥¤¥ë¹â");
4738 m = NewMenu(136, "\pTileHeight");
4741 /* Insert the menu */
4744 /* Add some sizes */
4745 for (i = 4; i <= 32; i++)
4750 sprintf((char*)buf + 1, "%d", i);
4751 buf[0] = strlen((char*)buf + 1);
4758 /* Update the menu bar */
4766 static void setup_menus(void)
4776 term_data *td = NULL;
4779 /* Relevant "term_data" */
4780 for (i = 0; i < MAX_TERM_DATA; i++)
4783 if (!data[i].t) continue;
4785 /* Notice the matching window */
4786 if (data[i].w == FrontWindow()) td = &data[i];
4791 m = GetMenuHandle(129);
4794 #if TARGET_API_MAC_CARBON
4795 n = CountMenuItems(m);
4801 for (i = 1; i <= n; i++)
4804 #if TARGET_API_MAC_CARBON
4805 DisableMenuItem(m, i);
4806 CheckMenuItem(m, i, FALSE);
4809 CheckItem(m, i, FALSE);
4813 /* Enable "new"/"open..."/"import..." */
4814 if (initialized && !game_in_progress)
4816 #if TARGET_API_MAC_CARBON
4817 EnableMenuItem(m, 1);
4818 EnableMenuItem(m, 2);
4819 EnableMenuItem(m, 3);
4827 /* Enable "close" */
4830 #if TARGET_API_MAC_CARBON
4831 EnableMenuItem(m, 4);
4838 if (initialized && character_generated)
4840 #if TARGET_API_MAC_CARBON
4841 EnableMenuItem(m, 5);
4850 #if TARGET_API_MAC_CARBON
4851 EnableMenuItem(m, 7);
4859 m = GetMenuHandle(130);
4862 #if TARGET_API_MAC_CARBON
4863 n = CountMenuItems(m);
4869 for (i = 1; i <= n; i++)
4872 #if TARGET_API_MAC_CARBON
4873 DisableMenuItem(m, i);
4874 CheckMenuItem(m, i, FALSE);
4877 CheckItem(m, i, FALSE);
4881 /* Enable "edit" options if "needed" */
4884 #if TARGET_API_MAC_CARBON
4885 EnableMenuItem(m, 1);
4886 EnableMenuItem(m, 3);
4887 EnableMenuItem(m, 4);
4888 EnableMenuItem(m, 5);
4889 EnableMenuItem(m, 6);
4901 m = GetMenuHandle(131);
4904 #if TARGET_API_MAC_CARBON
4905 n = CountMenuItems(m);
4911 for (i = 1; i <= n; i++)
4914 #if TARGET_API_MAC_CARBON
4915 DisableMenuItem(m, i);
4916 CheckMenuItem(m, i, FALSE);
4919 CheckItem(m, i, FALSE);
4923 /* Hack -- look cute XXX XXX */
4924 /* SetItemStyle(m, 1, bold); */
4926 /* Hack -- look cute XXX XXX */
4927 /* SetItemStyle(m, 2, extend); */
4932 #if TARGET_API_MAC_CARBON
4934 EnableMenuItem(m, 1);
4936 /* Enable "extend" */
4937 EnableMenuItem(m, 2);
4939 /* Check the appropriate "bold-ness" */
4940 if (td->font_face & bold) CheckMenuItem(m, 1, TRUE);
4942 /* Check the appropriate "wide-ness" */
4943 if (td->font_face & extend) CheckMenuItem(m, 2, TRUE);
4946 for (i = 4; i <= n; i++)
4949 EnableMenuItem(m, i);
4952 GetMenuItemText(m, i, s);
4955 /* Check active font */
4956 if (td->font_id == value) CheckMenuItem(m, i, TRUE);
4962 /* Enable "extend" */
4965 /* Check the appropriate "bold-ness" */
4966 if (td->font_face & bold) CheckItem(m, 1, TRUE);
4968 /* Check the appropriate "wide-ness" */
4969 if (td->font_face & extend) CheckItem(m, 2, TRUE);
4972 for (i = 4; i <= n; i++)
4978 GetMenuItemText(m, i, s);
4981 /* Check active font */
4982 if (td->font_id == value) CheckItem(m, i, TRUE);
4989 m = GetMenuHandle(132);
4992 #if TARGET_API_MAC_CARBON
4993 n = CountMenuItems(m);
4999 for (i = 1; i <= n; i++)
5002 #if TARGET_API_MAC_CARBON
5003 DisableMenuItem(m, i);
5004 CheckMenuItem(m, i, FALSE);
5007 CheckItem(m, i, FALSE);
5015 for (i = 1; i <= n; i++)
5017 #if TARGET_API_MAC_CARBON
5019 GetMenuItemText(m, i, s);
5021 value = atoi((char*)(s+1));
5023 /* Enable the "real" sizes */
5024 if (RealFont(td->font_id, value)) EnableMenuItem(m, i);
5026 /* Check the current size */
5027 if (td->font_size == value) CheckMenuItem(m, i, TRUE);
5030 GetMenuItemText(m, i, s);
5032 value = atoi((char*)(s+1));
5034 /* Enable the "real" sizes */
5035 if (RealFont(td->font_id, value)) EnableItem(m, i);
5037 /* Check the current size */
5038 if (td->font_size == value) CheckItem(m, i, TRUE);
5045 m = GetMenuHandle(133);
5048 #if TARGET_API_MAC_CARBON
5049 n = CountMenuItems(m);
5054 /* Check active windows */
5055 for (i = 1; i <= n; i++)
5057 /* Check if needed */
5058 #if TARGET_API_MAC_CARBON
5059 CheckMenuItem(m, i, data[i-1].mapped);
5061 CheckItem(m, i, data[i-1].mapped);
5067 m = GetMenuHandle(134);
5070 #if TARGET_API_MAC_CARBON
5071 n = CountMenuItems(m);
5077 for (i = 1; i <= n; i++)
5080 #if TARGET_API_MAC_CARBON
5081 DisableMenuItem(m, i);
5082 CheckMenuItem(m, i, FALSE);
5085 CheckItem(m, i, FALSE);
5089 #if TARGET_API_MAC_CARBON
5090 /* Item "arg_sound" */
5091 EnableMenuItem(m, 1);
5092 CheckMenuItem(m, 1, arg_sound);
5094 /* Item "arg_graphics" */
5095 EnableMenuItem(m, 2);
5096 CheckMenuItem(m, 2, arg_graphics);
5098 /* Item "arg_fiddle" */
5099 EnableMenuItem(m, 4);
5100 CheckMenuItem(m, 4, arg_fiddle);
5102 /* Item "arg_wizard" */
5103 EnableMenuItem(m, 5);
5104 CheckMenuItem(m, 5, arg_wizard);
5106 /* Item "SoundSetting" */
5107 EnableMenuItem(m, 7);
5109 /* Item NewStyle Graphics */
5110 EnableMenuItem(m, 8);
5111 CheckMenuItem(m, 8, use_newstyle_graphics);
5113 /* Item Bigtile Mode */
5114 EnableMenuItem(m, 9);
5115 CheckMenuItem(m, 9, arg_bigtile);
5117 /* Item "arg_sound" */
5119 CheckItem(m, 1, arg_sound);
5121 /* Item "arg_graphics" */
5123 CheckItem(m, 2, arg_graphics);
5125 /* Item "arg_fiddle" */
5127 CheckItem(m, 4, arg_fiddle);
5129 /* Item "arg_wizard" */
5131 CheckItem(m, 5, arg_wizard);
5133 /* Item "SoundSetting" */
5136 /* Item NewStyle Graphics */
5138 CheckItem(m, 8, use_newstyle_graphics);
5140 /* Item Bigtile Mode */
5142 CheckItem(m, 9, arg_bigtile);
5145 /* TileWidth menu */
5146 m = GetMenuHandle(135);
5149 #if TARGET_API_MAC_CARBON
5150 n = CountMenuItems(m);
5156 for (i = 1; i <= n; i++)
5159 #if TARGET_API_MAC_CARBON
5160 DisableMenuItem(m, i);
5161 CheckMenuItem(m, i, FALSE);
5164 CheckItem(m, i, FALSE);
5172 for (i = 1; i <= n; i++)
5175 /* GetMenuItemText(m,i,s); */
5176 GetMenuItemText(m, i, s);
5178 value = atoi((char*)(s+1));
5180 #if TARGET_API_MAC_CARBON
5182 EnableMenuItem(m, i);
5184 /* Check the current size */
5185 if (td->tile_wid == value) CheckMenuItem(m, i, TRUE);
5190 /* Check the current size */
5191 if (td->tile_wid == value) CheckItem(m, i, TRUE);
5197 /* TileHeight menu */
5198 m = GetMenuHandle(136);
5201 #if TARGET_API_MAC_CARBON
5202 n = CountMenuItems(m);
5208 for (i = 1; i <= n; i++)
5211 #if TARGET_API_MAC_CARBON
5212 DisableMenuItem(m, i);
5213 CheckMenuItem(m, i, FALSE);
5216 CheckItem(m, i, FALSE);
5224 for (i = 1; i <= n; i++)
5227 GetMenuItemText(m, i, s);
5229 value = atoi((char*)(s+1));
5231 #if TARGET_API_MAC_CARBON
5233 EnableMenuItem(m, i);
5235 /* Check the current size */
5236 if (td->tile_hgt == value) CheckMenuItem(m, i, TRUE);
5241 /* Check the current size */
5242 if (td->tile_hgt == value) CheckItem(m, i, TRUE);
5250 * Process a menu selection (see above)
5252 * Hack -- assume that invalid menu selections are disabled above,
5253 * which I have been informed may not be reliable. XXX XXX XXX
5255 static void menu(long mc)
5259 int menuid, selection;
5261 static unsigned char s[1000];
5265 term_data *td = NULL;
5270 /* Analyze the menu command */
5271 menuid = HiWord(mc);
5272 selection = LoWord(mc);
5275 /* Find the window */
5276 for (i = 0; i < MAX_TERM_DATA; i++)
5278 /* Skip dead windows */
5279 if (!data[i].t) continue;
5281 /* Notice matches */
5282 if (data[i].w == FrontWindow()) td = &data[i];
5286 /* Branch on the menu */
5292 /* About Angband... */
5293 #if TARGET_API_MAC_CARBON
5299 /* Get the about dialogue */
5300 dialog=GetNewDialog(128, 0, (WindowPtr)-1);
5302 /* Move it to the middle of the screen */
5304 GetDialogWindow(dialog),
5306 kWindowCenterOnMainScreen);
5308 /* Show the dialog */
5309 TransitionWindow(GetDialogWindow(dialog),
5310 kWindowZoomTransitionEffect,
5311 kWindowShowTransitionAction,
5314 /* Wait for user to click on it */
5315 ModalDialog(0, &item_hit);
5317 /* Free the dialogue */
5318 DisposeDialog(dialog);
5328 dialog=GetNewDialog(128, 0, (WindowPtr)-1);
5331 center_rect(&r, &qd.screenBits.bounds);
5332 MoveWindow(dialog, r.left, r.top, 1);
5334 ModalDialog(0, &item_hit);
5335 DisposeDialog(dialog);
5339 /* Desk accessory */
5340 /* GetMenuItemText(GetMHandle(128),selection,s); */
5341 GetMenuItemText(GetMenuHandle(128), selection, s);
5362 do_menu_file_open(FALSE);
5369 do_menu_file_open(TRUE);
5383 td->t->mapped_flag = FALSE;
5385 /* Hide the window */
5396 plog("º£¤Ï¥»¡¼¥Ö¤¹¤ë¤³¤È¤Ï½ÐÍè¤Þ¤»¤ó¡£");
5398 plog("You may not do that right now.");
5403 /* Hack -- Forget messages */
5406 /* Hack -- Save the game */
5407 do_cmd_save_game(FALSE);
5412 /* Quit (with save) */
5415 /* Save the game (if necessary) */
5416 if (game_in_progress && character_generated)
5420 plog("º£¤Ï¥»¡¼¥Ö¤¹¤ë¤³¤È¤Ï½ÐÍè¤Þ¤»¤ó¡£");
5422 plog("You may not do that right now.");
5426 /* Hack -- Forget messages */
5431 do_cmd_save_game(FALSE);
5433 Term_key_push(SPECIAL_KEY_QUIT);
5455 /* Require a window */
5464 /* Toggle the "bold" setting */
5467 /* Toggle the setting */
5468 if (td->font_face & bold)
5470 td->font_face &= ~bold;
5474 td->font_face |= bold;
5477 /* Tile Width Hight Init */
5478 td->tile_wid = td->tile_hgt = 0;
5480 /* Apply and Verify */
5481 term_data_check_font(td);
5482 term_data_check_size(td);
5484 /* Resize and Redraw */
5485 term_data_resize(td);
5486 term_data_redraw(td);
5491 /* Toggle the "wide" setting */
5494 /* Toggle the setting */
5495 if (td->font_face & extend)
5497 td->font_face &= ~extend;
5501 td->font_face |= extend;
5504 /* Tile Width Hight Init */
5505 td->tile_wid = td->tile_hgt = 0;
5507 /* Apply and Verify */
5508 term_data_check_font(td);
5509 term_data_check_size(td);
5511 /* Resize and Redraw */
5512 term_data_resize(td);
5513 term_data_redraw(td);
5518 /* Get a new font name */
5519 GetMenuItemText(GetMenuHandle(131), selection, s);
5522 /* Save the new font id */
5525 /* Current size is bad for new font */
5526 if (!RealFont(td->font_id, td->font_size))
5528 /* Find similar size */
5529 for (i = 1; i <= 32; i++)
5531 /* Adjust smaller */
5532 if (td->font_size - i >= 8)
5534 if (RealFont(td->font_id, td->font_size - i))
5542 if (td->font_size + i <= 128)
5544 if (RealFont(td->font_id, td->font_size + i))
5553 /* Tile Width Hight Init */
5554 td->tile_wid = td->tile_hgt = 0;
5556 /* Apply and Verify */
5557 term_data_check_font(td);
5558 term_data_check_size(td);
5560 /* Resize and Redraw */
5561 term_data_resize(td);
5562 term_data_redraw(td);
5564 /* Restore the window */
5581 GetMenuItemText(GetMenuHandle(132), selection, s);
5583 td->font_size = atoi((char*)(s+1));
5585 /* Tile Width Hight Init */
5586 td->tile_wid = td->tile_hgt = 0;
5588 /* Apply and Verify */
5589 term_data_check_font(td);
5590 term_data_check_size(td);
5592 /* Resize and Redraw */
5593 term_data_resize(td);
5594 term_data_redraw(td);
5608 /* Check legality of choice */
5609 if ((i < 0) || (i >= MAX_TERM_DATA)) break;
5611 /* Obtain the window */
5621 td->t->mapped_flag = TRUE;
5623 /* Show the window */
5626 /* Bring to the front */
5627 SelectWindow(td->w);
5639 /* Toggle arg_sound */
5640 arg_sound = !arg_sound;
5642 /* React to changes */
5643 Term_xtra(TERM_XTRA_REACT, 0);
5650 /* Toggle arg_graphics */
5651 arg_graphics = !arg_graphics;
5652 if( arg_graphics == true ){
5653 ANGBAND_GRAF = "old";
5654 arg_newstyle_graphics = false;
5655 grafWidth = grafHeight = 8;
5659 /* Hack -- Force redraw */
5660 Term_key_push(KTRL('R'));
5667 arg_fiddle = !arg_fiddle;
5673 arg_wizard = !arg_wizard;
5684 if (streq(ANGBAND_GRAF, "old"))
5686 ANGBAND_GRAF = "new";
5687 arg_newstyle_graphics = true;
5688 grafWidth = grafHeight = 16;
5693 ANGBAND_GRAF = "old";
5694 arg_newstyle_graphics = false;
5695 grafWidth = grafHeight = 8;
5699 /* Hack -- Force redraw */
5700 Term_key_push(KTRL('R'));
5704 case 9: /* bigtile mode */
5706 term_data *td = &data[0];
5710 plog("º£¤ÏÊѹ¹½ÐÍè¤Þ¤»¤ó¡£");
5712 plog("You may not do that right now.");
5717 /* Toggle "arg_bigtile" */
5718 arg_bigtile = !arg_bigtile;
5721 Term_activate(td->t);
5723 /* Resize the term */
5724 Term_resize(td->cols, td->rows);
5734 /* TileWidth menu */
5745 GetMenuItemText(GetMenuHandle(135), selection, s);
5747 td->tile_wid = atoi((char*)(s+1));
5749 /* Apply and Verify */
5750 term_data_check_size(td);
5752 /* Resize and Redraw */
5753 term_data_resize(td);
5754 term_data_redraw(td);
5762 /* TileHeight menu */
5773 GetMenuItemText(GetMenuHandle(136), selection, s);
5775 td->tile_hgt = atoi((char*)(s+1));
5777 /* Apply and Verify */
5778 term_data_check_size(td);
5780 /* Resize and Redraw */
5781 term_data_resize(td);
5782 term_data_redraw(td);
5792 /* Clean the menu */
5801 * Check for extra required parameters -- From "Maarten Hazewinkel"
5803 static OSErr CheckRequiredAEParams(const AppleEvent *theAppleEvent)
5806 DescType returnedType;
5809 aeError = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard,
5810 &returnedType, NULL, 0, &actualSize);
5812 if (aeError == errAEDescNotFound) return (noErr);
5814 if (aeError == noErr) return (errAEParamMissed);
5821 * Apple Event Handler -- Open Application
5823 static pascal OSErr AEH_Start(const AppleEvent *theAppleEvent,
5824 AppleEvent *reply, long handlerRefCon)
5826 #pragma unused(reply, handlerRefCon)
5828 return (CheckRequiredAEParams(theAppleEvent));
5833 * Apple Event Handler -- Quit Application
5835 static pascal OSErr AEH_Quit(const AppleEvent *theAppleEvent,
5836 AppleEvent *reply, long handlerRefCon)
5838 #pragma unused(reply, handlerRefCon)
5839 #if TARGET_API_MAC_CARBON
5841 /* Save the game (if necessary) */
5842 if (game_in_progress && character_generated)
5846 plog("º£¤Ï¥»¡¼¥Ö¤¹¤ë¤³¤È¤Ï½ÐÍè¤Þ¤»¤ó¡£");
5848 plog("You may not do that right now.");
5852 /* Hack -- Forget messages */
5857 do_cmd_save_game(FALSE);
5859 Term_key_push(SPECIAL_KEY_QUIT);
5867 quit_when_ready = TRUE;
5869 /* Check arguments */
5870 return (CheckRequiredAEParams(theAppleEvent));
5876 * Apple Event Handler -- Print Documents
5878 static pascal OSErr AEH_Print(const AppleEvent *theAppleEvent,
5879 AppleEvent *reply, long handlerRefCon)
5881 #pragma unused(theAppleEvent, reply, handlerRefCon)
5883 return (errAEEventNotHandled);
5888 * Apple Event Handler by Steve Linberg (slinberg@crocker.com).
5890 * The old method of opening savefiles from the finder does not work
5891 * on the Power Macintosh, because CountAppFiles and GetAppFiles,
5892 * used to return information about the selected document files when
5893 * an application is launched, are part of the Segment Loader, which
5894 * is not present in the RISC OS due to the new memory architecture.
5896 * The "correct" way to do this is with AppleEvents. The following
5897 * code is modeled on the "Getting Files Selected from the Finder"
5898 * snippet from Think Reference 2.0. (The prior sentence could read
5899 * "shamelessly swiped & hacked")
5901 static pascal OSErr AEH_Open(const AppleEvent *theAppleEvent,
5902 AppleEvent* reply, long handlerRefCon)
5904 #pragma unused(reply, handlerRefCon)
5911 DescType returnedType;
5915 /* Put the direct parameter (a descriptor list) into a docList */
5916 err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &docList);
5917 if (err) return err;
5920 * We ignore the validity check, because we trust the FInder, and we only
5921 * allow one savefile to be opened, so we ignore the depth of the list.
5924 err = AEGetNthPtr(&docList, 1L, typeFSS, &keywd,
5925 &returnedType, (Ptr) &myFSS, sizeof(myFSS), &actualSize);
5926 if (err) return err;
5928 /* Only needed to check savefile type below */
5929 err = FSpGetFInfo(&myFSS, &myFileInfo);
5932 sprintf(foo, "Arg! FSpGetFInfo failed with code %d", err);
5937 /* Ignore non 'SAVE' files */
5938 if (myFileInfo.fdType != 'SAVE') return noErr;
5940 #ifdef MACH_O_CARBON
5942 /* Extract a file name */
5943 (void)spec_to_path(&myFSS, savefile, sizeof(savefile));
5947 /* XXX XXX XXX Extract a file name */
5948 PathNameFromDirID(myFSS.parID, myFSS.vRefNum, (StringPtr)savefile);
5949 pstrcat((StringPtr)savefile, (StringPtr)&myFSS.name);
5951 /* Convert the string */
5952 ptocstr((StringPtr)savefile);
5954 #endif /* MACH_O_CARBON */
5956 /* Delay actual open */
5957 open_when_ready = TRUE;
5960 err = AEDisposeDesc(&docList);
5972 * Macintosh modifiers (event.modifier & ccc):
5973 * cmdKey, optionKey, shiftKey, alphaLock, controlKey
5976 * Macintosh Keycodes (0-63 normal, 64-95 keypad, 96-127 extra):
6021 * Optimize non-blocking calls to "CheckEvents()"
6022 * Idea from "Maarten Hazewinkel <mmhazewi@cs.ruu.nl>"
6024 #define EVENT_TICKS 6
6028 * Check for Events, return TRUE if we process any
6030 * Hack -- Handle AppleEvents if appropriate (ignore result code).
6032 static bool CheckEvents(bool wait)
6048 term_data *td = NULL;
6052 static huge lastTicks = 0L;
6055 /* Access the clock */
6056 curTicks = TickCount();
6058 /* Hack -- Allow efficient checking for non-pending events */
6059 if (!wait && (curTicks < lastTicks + EVENT_TICKS)) return (FALSE);
6061 /* Timestamp last check */
6062 lastTicks = curTicks;
6064 #if TARGET_API_MAC_CARBON
6065 WaitNextEvent( everyEvent, &event, 1L, nil );
6067 /* Let the "system" run */
6070 /* Get an event (or null) */
6071 GetNextEvent(everyEvent, &event);
6074 /* Hack -- Nothing is ready yet */
6075 if (event.what == nullEvent) return (FALSE);
6077 /* Analyze the event */
6085 w = (WindowPtr)event.message;
6096 /* Extract the window */
6097 w = (WindowPtr)event.message;
6099 /* Find the window */
6100 for (i = 0; i < MAX_TERM_DATA; i++)
6102 /* Skip dead windows */
6103 if (!data[i].t) continue;
6105 /* Notice matches */
6106 if (data[i].w == w) td = &data[i];
6109 /* Hack XXX XXX XXX */
6113 /* Redraw the window */
6114 if (td) term_data_redraw(td);
6122 /* Extract some modifiers */
6123 mc = (event.modifiers & controlKey) ? TRUE : FALSE;
6124 ms = (event.modifiers & shiftKey) ? TRUE : FALSE;
6125 mo = (event.modifiers & optionKey) ? TRUE : FALSE;
6126 mx = (event.modifiers & cmdKey) ? TRUE : FALSE;
6128 /* Keypress: (only "valid" if ck < 96) */
6129 ch = (event.message & charCodeMask) & 255;
6131 /* Keycode: see table above */
6132 ck = ((event.message & keyCodeMask) >> 8) & 255;
6134 /* Command + "normal key" -> menu action */
6135 if (mx && (ck < 64))
6137 /* Hack -- Prepare the menus */
6140 /* Run the Menu-Handler */
6143 /* Turn off the menus */
6151 /* Hide the mouse pointer */
6154 /* Normal key -> simple keypress */
6157 /* Enqueue the keypress */
6161 /* Bizarre key -> encoded keypress */
6164 /* Hack -- introduce with control-underscore */
6167 /* Send some modifier keys */
6168 if (mc) Term_keypress('C');
6169 if (ms) Term_keypress('S');
6170 if (mo) Term_keypress('O');
6171 if (mx) Term_keypress('X');
6173 /* Hack -- Downshift and encode the keycode */
6174 Term_keypress('0' + (ck - 64) / 10);
6175 Term_keypress('0' + (ck - 64) % 10);
6177 /* Hack -- Terminate the sequence */
6178 /* MPW can generate 10 or 13 for keycode of '\r' */
6179 /* -noMapCR option swaps '\r' and '\n' */
6180 Term_keypress('\r');
6190 /* Analyze click location */
6191 code = FindWindow(event.where, &w);
6193 /* Find the window */
6194 for (i = 0; i < MAX_TERM_DATA; i++)
6196 /* Skip dead windows */
6197 if (!data[i].t) continue;
6199 /* Notice matches */
6200 if (data[i].w == w) td = &data[i];
6209 menu(MenuSelect(event.where));
6213 #if !TARGET_API_MAC_CARBON
6216 SystemClick(&event, w);
6228 #if TARGET_API_MAC_CARBON
6229 GetQDGlobalsScreenBits( &screen );
6231 screen = qd.screenBits;
6234 r.top += 20; /* GetMBarHeight() XXX XXX XXX */
6235 InsetRect(&r, 4, 4);
6236 DragWindow(w, event.where, &r);
6248 #if TARGET_API_MAC_CARBON
6249 GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &portRect );
6251 portRect = td->w->portRect;
6252 local_to_global( &portRect );
6254 p.h = portRect.left;
6256 #if !TARGET_API_MAC_CARBON
6265 /* Apply and Verify */
6266 term_data_check_size(td);
6276 /* Track the go-away box */
6277 if (TrackGoAway(w, event.where))
6283 td->t->mapped_flag = FALSE;
6285 /* Hide the window */
6299 #if TARGET_API_MAC_CARBON
6300 GetQDGlobalsScreenBits( &screen );
6302 screen = qd.screenBits;
6307 /* Fake rectangle */
6308 r.left = 20 * td->tile_wid + td->size_ow1;
6309 r.right = screen.bounds.right;
6310 r.top = 1 * td->tile_hgt + td->size_oh1;
6311 r.bottom = screen.bounds.bottom;
6313 /* Grow the rectangle */
6314 newsize = GrowWindow(w, event.where, &r);
6317 if (!newsize) break;
6319 /* Extract the new size in pixels */
6320 y = HiWord(newsize) - td->size_oh1 - td->size_oh2;
6321 x = LoWord(newsize) - td->size_ow1 - td->size_ow2;
6323 /* Extract a "close" approximation */
6324 td->rows = y / td->tile_hgt;
6325 td->cols = x / td->tile_wid;
6327 /* Apply and Verify */
6328 term_data_check_size(td);
6330 Term_activate(td->t);
6332 /* Hack -- Resize the term */
6333 Term_resize(td->cols, td->rows);
6335 /* Resize and Redraw */
6336 term_data_resize(td);
6337 term_data_redraw(td);
6356 /* Disk Event -- From "Maarten Hazewinkel" */
6360 #if TARGET_API_MAC_CARBON
6362 /* check for error when mounting the disk */
6363 if (HiWord(event.message) != noErr)
6369 DIBadMount(p, event.message);
6376 /* OS Event -- From "Maarten Hazewinkel" */
6379 switch ((event.message >> 24) & 0x000000FF)
6381 case suspendResumeMessage:
6383 /* Resuming: activate the front window */
6384 if (event.message & resumeFlag)
6386 #if TARGET_API_MAC_CARBON
6389 SetPortWindowPort( FrontWindow() );
6391 GetQDGlobalsArrow( &arrow );
6394 SetPort(FrontWindow());
6395 SetCursor(&qd.arrow);
6399 /* Suspend: deactivate the front window */
6413 /* From "Steve Linberg" and "Maarten Hazewinkel" */
6414 case kHighLevelEvent:
6416 #if TARGET_API_MAC_CARBON
6417 AEProcessAppleEvent(&event);
6419 /* Process apple events */
6420 if (AEProcessAppleEvent(&event) != noErr)
6423 plog("Apple Event Handler¤Î¥¨¥é¡¼¤Ç¤¹.");
6425 plog("Error in Apple Event Handler!");
6429 /* Handle "quit_when_ready" */
6430 if (quit_when_ready)
6433 quit_when_ready = FALSE;
6435 /* Do the menu key */
6438 /* Turn off the menus */
6442 /* Handle "open_when_ready" */
6443 handle_open_when_ready();
6454 /* Something happened */
6461 /*** Some Hooks for various routines ***/
6465 * Mega-Hack -- emergency lifeboat
6467 static vptr lifeboat = NULL;
6471 * Hook to "release" memory
6473 static vptr hook_rnfree(vptr v, huge size)
6476 #pragma unused (size)
6480 /* Alternative method */
6495 * Hook to "allocate" memory
6497 static vptr hook_ralloc(huge size)
6502 /* Make a new pointer */
6503 return (malloc(size));
6507 /* Make a new pointer */
6508 return (NewPtr(size));
6515 * Hook to handle "out of memory" errors
6517 static vptr hook_rpanic(huge size)
6520 #pragma unused (size)
6522 /* vptr mem = NULL; */
6524 /* Free the lifeboat */
6527 /* Free the lifeboat */
6528 DisposePtr(lifeboat);
6530 /* Forget the lifeboat */
6533 /* Mega-Hack -- Warning */
6535 mac_warning("¥á¥â¥ê¡¼¤¬Â¤ê¤Þ¤»¤ó!\rº£¤¹¤°½ªÎ»¤·¤Æ²¼¤µ¤¤!");
6537 mac_warning("Running out of Memory!\rAbort this process now!");
6540 /* Mega-Hack -- Never leave this function */
6541 while (TRUE) CheckEvents(TRUE);
6544 /* Mega-Hack -- Crash */
6550 * Hook to tell the user something important
6552 static void hook_plog(cptr str)
6554 /* Warning message */
6559 * Hook to tell the user something, and then quit
6561 static void hook_quit(cptr str)
6563 /* Warning if needed */
6564 if (str) mac_warning(str);
6566 #ifdef USE_ASYNC_SOUND
6568 /* Clean up sound support */
6571 #endif /* USE_ASYNC_SOUND */
6573 /* Write a preference file */
6581 * Hook to tell the user something, and then crash
6583 static void hook_core(cptr str)
6585 /* XXX Use the debugger */
6586 /* DebugStr(str); */
6589 if (str) mac_warning(str);
6591 /* Warn, then save player */
6593 mac_warning("Ã×̿Ū¤Ê¥¨¥é¡¼¤Ç¤¹.\r¶¯À©Åª¤Ë¥»¡¼¥Ö¤·¤Æ½ªÎ»¤·¤Þ¤¹.");
6595 mac_warning("Fatal error.\rI will now attempt to save and quit.");
6598 /* Attempt to save */
6600 if (!save_player()) mac_warning("·Ù¹ð -- ¥»¡¼¥Ö¤Ë¼ºÇÔ¤·¤Þ¤·¤¿!");
6602 if (!save_player()) mac_warning("Warning -- save failed!");
6611 /*** Main program ***/
6617 * XXX XXX XXX Hack -- This function attempts to "fix" the nasty
6618 * "Macintosh Save Bug" by using "absolute" path names, since on
6619 * System 7 machines anyway, the "current working directory" often
6620 * "changes" due to background processes, invalidating any "relative"
6621 * path names. Note that the Macintosh is limited to 255 character
6622 * path names, so be careful about deeply embedded directories...
6624 * XXX XXX XXX Hack -- This function attempts to "fix" the nasty
6625 * "missing lib folder bug" by allowing the user to help find the
6626 * "lib" folder by hand if the "application folder" code fails...
6628 static void init_stuff(void)
6632 #if !TARGET_API_MAC_CARBON
6649 #if TARGET_API_MAC_CARBON
6651 NavDialogOptions dialogOptions;
6652 FSSpec theFolderSpec;
6653 NavReplyRecord theReply;
6655 /* Fake rectangle */
6662 #if TARGET_API_MAC_CARBON
6663 screenRect = GetQDGlobalsScreenBits(&screen)->bounds;
6665 screenRect = qd.screenBits.bounds;
6667 center_rect(&r, &screenRect);
6669 /* Extract corner */
6674 /* Default to the "lib" folder with the application */
6675 #ifdef MACH_O_CARBON
6676 if (locate_lib(path, sizeof(path)) == NULL) quit(NULL);
6678 refnum_to_name(path, app_dir, app_vol, (char*)("\plib:"));
6682 /* Check until done */
6685 /* Prepare the paths */
6686 init_file_paths(path);
6688 /* Build the filename */
6690 path_build(path, sizeof(path), ANGBAND_DIR_FILE, "news_j.txt");
6692 path_build(path, sizeof(path), ANGBAND_DIR_FILE, "news.txt");
6695 /* Attempt to open and close that file */
6696 if (0 == fd_close(fd_open(path, O_RDONLY))) break;
6700 plog_fmt("'%s' ¥Õ¥¡¥¤¥ë¤ò¥ª¡¼¥×¥ó½ÐÍè¤Þ¤»¤ó.", path);
6702 plog_fmt("Unable to open the '%s' file.", path);
6707 plog("Hengband¤Î'lib'¥Õ¥©¥ë¥À¤¬Â¸ºß¤·¤Ê¤¤¤«Àµ¤·¤¯Ìµ¤¤²ÄǽÀ¤¬¤¢¤ê¤Þ¤¹.");
6709 plog("The Angband 'lib' folder is probably missing or misplaced.");
6714 plog("Please 'open' any file in any sub-folder of the 'lib' folder.");
6716 plog("Please 'open' any file in any sub-folder of the 'lib' folder.");
6719 #if TARGET_API_MAC_CARBON
6720 /* Ask the user to choose the lib folder */
6721 err = NavGetDefaultDialogOptions(&dialogOptions);
6724 if (err != noErr) quit(NULL);
6726 /* Set default location option */
6727 dialogOptions.dialogOptionFlags |= kNavSelectDefaultLocation;
6729 /* Clear preview option */
6730 dialogOptions.dialogOptionFlags &= ~(kNavAllowPreviews);
6732 /* Forbit selection of multiple files */
6733 dialogOptions.dialogOptionFlags &= ~(kNavAllowMultipleFiles);
6735 /* Display location */
6736 dialogOptions.location = topleft;
6738 /* Load the message for the missing folder from the resource fork */
6739 GetIndString(dialogOptions.message, 128, 1);
6741 /* Wait for the user to choose a folder */
6742 err = NavChooseFolder(
6750 /* Assume the player doesn't want to go on */
6751 if ((err != noErr) || !theReply.validRecord) quit(NULL);
6753 /* Retrieve FSSpec from the reply */
6755 AEKeyword theKeyword;
6756 DescType actualType;
6759 /* Get a pointer to selected folder */
6761 &(theReply.selection),
6771 if (err != noErr) quit(NULL);
6774 /* Free navitagor reply */
6775 err = NavDisposeReply(&theReply);
6778 if (err != noErr) quit(NULL);
6780 /* Extract textual file name for given file */
6783 theFolderSpec.parID,
6784 theFolderSpec.vRefNum,
6785 (char *)theFolderSpec.name);
6787 /* Allow "text" files */
6790 /* Allow "save" files */
6793 /* Allow "data" files */
6797 SFGetFile(topleft, "\p", NULL, 3, types, NULL, &reply);
6800 if (!reply.good) quit(NULL);
6802 /* Extract textual file name for given file */
6803 GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
6804 refnum_to_name(path, drefnum, vrefnum, (char*)reply.fName);
6807 /* Hack -- Remove the "filename" */
6808 i = strlen(path) - 1;
6809 while ((i > 0) && (path[i] != ':')) i--;
6810 if (path[i] == ':') path[i+1] = '\0';
6812 /* Hack -- allow "lib" folders */
6813 if (suffix(path, "lib:")) continue;
6815 /* Hack -- Remove the "sub-folder" */
6817 while ((i > 1) && (path[i] != ':')) i--;
6818 if (path[i] == ':') path[i+1] = '\0';
6824 * Macintosh Main loop
6828 EventRecord tempEvent;
6829 int numberOfMasters = 10;
6831 #if !TARGET_API_MAC_CARBON
6832 /* Increase stack space by 64K */
6833 SetApplLimit(GetApplLimit() - 131072L);//65536L);
6835 /* Stretch out the heap to full size */
6839 /* Get more Masters */
6840 while (numberOfMasters--) MoreMasters();
6842 #if !TARGET_API_MAC_CARBON
6843 /* Set up the Macintosh */
6844 InitGraf(&qd.thePort);
6858 FlushEvents(everyEvent, 0);
6860 /* Flush events some more (?) */
6861 (void)EventAvail(everyEvent, &tempEvent);
6862 (void)EventAvail(everyEvent, &tempEvent);
6863 (void)EventAvail(everyEvent, &tempEvent);
6866 #ifdef ANGBAND_LITE_MAC
6870 #else /* ANGBAND_LITE_MAC */
6872 # if defined(powerc) || defined(__powerc)
6874 /* Assume System 7 */
6876 /* Assume Color Quickdraw */
6880 #if TARGET_API_MAC_CARBON
6886 /* Check for existence of Carbon */
6887 err = Gestalt(gestaltCarbonVersion, &response);
6889 if (err != noErr) quit("This program requires Carbon API");
6899 /* Check the Gestalt */
6900 err = Gestalt(gestaltSystemVersion, &versionNumber);
6902 /* Check the version */
6903 if ((err != noErr) || (versionNumber < 0x0700))
6906 quit("¤³¤Î¥×¥í¥°¥é¥à¤Ï´Á»úTalk7.x.x°Ê¹ß¤ÇÆ°ºî¤·¤Þ¤¹.");
6908 quit("You must have System 7 to use this program.");
6918 /* Check the environs */
6919 if (SysEnvirons(1, &env) != noErr)
6922 quit("SysEnvirons ¥³¡¼¥ë¤Ï¼ºÇÔ¤·¤Þ¤·¤¿¡ª");
6924 quit("The SysEnvirons call failed!");
6928 /* Check for System Seven Stuff */
6929 if (env.systemVersion < 0x0700)
6932 quit("¤³¤Î¥×¥í¥°¥é¥à¤Ï´Á»úTalk7.x.x°Ê¹ß¤ÇÆ°ºî¤·¤Þ¤¹.");
6934 quit("You must have System 7 to use this program.");
6938 /* Check for Color Quickdraw */
6939 if (!env.hasColorQD)
6942 quit("¤³¤Î¥×¥í¥°¥é¥à¤ÏColor Quickdraw¤¬Ìµ¤¤¤ÈÆ°ºî¤·¤Þ¤»¤ó.");
6944 quit("You must have Color Quickdraw to use this program.");
6952 #endif /* ANGBAND_LITE_MAC */
6955 * Remember Mac OS version, in case we have to cope with version-specific
6958 (void)Gestalt(gestaltSystemVersion, &mac_os_version);
6961 /* Obtain a "Universal Procedure Pointer" */
6962 AEH_Start_UPP = NewAEEventHandlerUPP(AEH_Start);
6963 /* Install the hook (ignore error codes) */
6964 AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, AEH_Start_UPP,
6967 /* Obtain a "Universal Procedure Pointer" */
6968 AEH_Quit_UPP = NewAEEventHandlerUPP(AEH_Quit);
6969 /* Install the hook (ignore error codes) */
6970 AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, AEH_Quit_UPP,
6973 /* Obtain a "Universal Procedure Pointer" */
6974 AEH_Print_UPP = NewAEEventHandlerUPP(AEH_Print);
6975 /* Install the hook (ignore error codes) */
6976 AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, AEH_Print_UPP,
6979 /* Obtain a "Universal Procedure Pointer" */
6980 AEH_Open_UPP = NewAEEventHandlerUPP(AEH_Open);
6981 /* Install the hook (ignore error codes) */
6982 AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, AEH_Open_UPP,
6986 #ifndef MACH_O_CARBON
6987 /* Find the current application */
6991 /* Mark ourself as the file creator */
6992 _fcreator = ANGBAND_CREATOR;
6994 /* Default to saving a "text" file */
6998 #if defined(__MWERKS__)
7000 /* Obtian a "Universal Procedure Pointer" */
7001 #if TARGET_API_MAC_CARBON
7002 ynfilterUPP = NewModalFilterUPP(ynfilter);
7004 ynfilterUPP = NewModalFilterProc(ynfilter);
7010 /* Hook in some "z-virt.c" hooks */
7011 rnfree_aux = hook_rnfree;
7012 ralloc_aux = hook_ralloc;
7013 rpanic_aux = hook_rpanic;
7015 /* Hooks in some "z-util.c" hooks */
7016 plog_aux = hook_plog;
7017 quit_aux = hook_quit;
7018 core_aux = hook_core;
7020 BackColor(blackColor);
7021 ForeColor(whiteColor);
7023 /* Show the "watch" cursor */
7024 SetCursor(*(GetCursor(watchCursor)));
7026 /* Prepare the menubar */
7029 /* Prepare the windows */
7032 #ifndef MACH_O_CARBON
7040 /* Hack -- process all events */
7041 while (CheckEvents(TRUE)) /* loop */;
7043 /* Reset the cursor */
7044 #if TARGET_API_MAC_CARBON
7047 GetQDGlobalsArrow( &arrow );
7051 SetCursor( &qd.arrow );
7055 /* Mega-Hack -- Allocate a "lifeboat" */
7056 lifeboat = NewPtr(16384);
7058 /* Note the "system" */
7059 ANGBAND_SYS = "mac";
7064 /* Catch nasty signals */
7071 /* Hack -- process all events */
7072 while (CheckEvents(TRUE)) /* loop */;
7075 /* We are now initialized */
7079 /* Handle "open_when_ready" */
7080 handle_open_when_ready();
7086 /* Prompt the user */
7088 prt("'¥Õ¥¡¥¤¥ë'¥á¥Ë¥å¡¼¤è¤ê'¿·µ¬'¤Þ¤¿¤Ï'³«¤¯...'¤òÁªÂò¤·¤Æ¤¯¤À¤µ¤¤¡£", 23, 10);
7090 prt("[Choose 'New' or 'Open' from the 'File' menu]", 23, 15);
7093 /* Flush the prompt */
7097 /* Hack -- Process Events Forever */
7098 while (TRUE) CheckEvents(TRUE);