OSDN Git Service

切り裂きの大鎌『ブラッディ・ムーン』に関する変更.
[hengband/hengband.git] / src / main-mac.c
1 /* File: main-mac.c */
2
3 /* Purpose: Simple support for MACINTOSH Angband */
4
5 /*
6  * This file should only be compiled with the "Macintosh" version
7  *
8  * This file written by "Ben Harrison (benh@phial.com)".
9  *
10  * Some code adapted from "MacAngband 2.6.1" by Keith Randall
11  *
12  * Maarten Hazewinkel (mmhazewi@cs.ruu.nl) provided some initial
13  * suggestions for the PowerMac port.
14  *
15  * Steve Linberg (slinberg@crocker.com) provided the code surrounded
16  * by "USE_SFL_CODE".
17  *
18  * The graphics code is adapted from an extremely minimal subset of
19  * the code from "Sprite World II", an amazing animation package.
20  *
21  * See "z-term.c" for info on the concept of the "generic terminal"
22  *
23  * The preference file is now a text file named "Angband preferences".
24  *
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).
28  *
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.
32  *
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".
36  *
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.
41  *
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.
47  *
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.
51  *
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.
55  */
56
57
58 /*
59  * Important Resources in the resource file:
60  *
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)
65  *
66  *   DLOG 128 = "About Angband..."
67  *
68  *   ALRT 128 = unused (?)
69  *   ALRT 129 = "Warning..."
70  *   ALRT 130 = "Are you sure you want to quit without saving?"
71  *
72  *   DITL 128 = body for DLOG 128
73  *   DITL 129 = body for ALRT 129
74  *   DITL 130 = body for ALRT 130
75  *
76  *   ICON 128 = "warning" icon
77  *
78  *   MENU 128 = apple (about, -, ...)
79  *   MENU 129 = File (new, open, close, save, -, exit, quit)
80  *   MENU 130 = Edit (undo, -, cut, copy, paste, clear)
81  *
82  *   PICT 1001 = Graphics tile set
83  */
84
85
86 /*
87  * File name patterns:
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:*" (?)
93  *
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
98  */
99
100
101 /*
102  * Reasons for each header file:
103  *
104  *   angband.h = Angband header file
105  *
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
128  *
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
132  */
133
134
135 #include "angband.h"
136
137 #ifdef MACH_O_CARBON
138
139 #include <Carbon/Carbon.h>
140 #include <QuickTime/QuickTime.h>
141 #include <CoreServices/CoreServices.h>
142 #include <CoreFoundation/CoreFoundation.h>
143
144 #define TARGET_API_MAC_CARBON 1
145
146 #else /* MACH_O_CARBON */
147
148 #include <Types.h>
149 #include <Gestalt.h>
150 #include <QuickDraw.h>
151 #include <Files.h>
152 #include <Fonts.h>
153 #include <Menus.h>
154 #include <Dialogs.h>
155 #include <Windows.h>
156 #include <Palettes.h>
157 #include <StandardFile.h>
158 #include <DiskInit.h>
159 #include <ToolUtils.h>
160 #include <Devices.h>
161 #include <Events.h>
162 #include <Resources.h>
163 #include <Controls.h>
164 #include <SegLoad.h>
165 #include <Memory.h>
166 #include <QDOffscreen.h>
167 #include <Sound.h>
168 #if TARGET_API_MAC_CARBON
169 #include <Navigation.h>
170 #include <CFPreferences.h>
171 #include <CFNumber.h>
172 # ifdef MAC_MPW
173 # include <CarbonStdCLib.h>
174 # endif
175 #endif
176
177 #ifdef JP
178
179 #include <Script.h>
180
181 #endif
182
183 #endif /* MACH_O_CARBON */
184
185 /*
186  * Use rewritten asynchronous sound player
187  */
188 #define USE_ASYNC_SOUND
189
190 /*
191  * Cleaning up a couple of things to make these easier to change --AR
192  */
193 #ifdef JP
194 #define PREF_FILE_NAME "Hengband Preferences"
195 #else
196 #define PREF_FILE_NAME "Hengband-E Preferences"
197 #endif
198
199 /*
200  * Use "malloc()" instead of "NewPtr()"
201  */
202 /* #define USE_MALLOC */
203
204
205 /* Default creator signature */
206 #ifndef ANGBAND_CREATOR
207 # define ANGBAND_CREATOR 'Heng'
208 #endif
209
210
211 #if defined(powerc) || defined(__powerc)
212
213 /*
214  * Disable "LITE" version
215  */
216 # undef ANGBAND_LITE_MAC
217
218 #endif
219
220
221 #ifdef ANGBAND_LITE_MAC
222
223 /*
224  * Maximum number of windows
225  */
226 # define MAX_TERM_DATA 1
227
228 #else /* ANGBAND_LITE_MAC */
229
230 /*
231  * Maximum number of windows
232  */
233 # define MAX_TERM_DATA 8
234
235 /*
236  * Activate some special code
237  */
238 # define USE_SFL_CODE
239
240 #endif /* ANGBAND_LITE_MAC */
241
242
243
244 #ifndef MACH_O_CARBON
245 #ifdef USE_SFL_CODE
246
247 /*
248  * Include the necessary header files
249  */
250 #include <AppleEvents.h>
251 #include <EPPC.h>
252 #include <Folders.h>
253
254 #endif
255 #endif /* !MACH_O_CARBON */
256
257 /*
258  * Globals for MPW compilation
259  */
260 #if defined(MACH_O_CARBON) || defined(MAC_MPW)
261        /* Globals needed */
262 #if !TARGET_API_MAC_CARBON
263        QDGlobals qd;
264 #endif
265        OSType _ftype;
266        OSType _fcreator;
267 #endif
268
269
270
271 #if 0
272
273 /*
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
277  *
278  * Colors 8 to 15 are basically "enhanced" versions of Colors 0 to 7.
279  *
280  * On the Macintosh, we use color quickdraw, and we use actual "RGB"
281  * values below to choose the 16 colors.
282  *
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).
286  */
287 static RGBColor foo[16] =
288 {
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 */
305 };
306
307 #endif
308
309
310 /*
311  * Forward declare
312  */
313 typedef struct term_data term_data;
314
315 /*
316  * Extra "term" data
317  */
318 struct term_data
319 {
320         term            *t;
321
322         Rect            r;
323
324         WindowPtr       w;
325
326 #ifdef ANGBAND_LITE_MAC
327
328         /* Nothing */
329
330 #else /* ANGBAND_LITE_MAC */
331
332         short padding;
333
334         short pixelDepth;
335
336         GWorldPtr theGWorld;
337
338         GDHandle theGDH;
339
340         GDHandle mainSWGDH;
341
342 #endif /* ANGBAND_LITE_MAC */
343
344         Str15           title;
345
346         s16b            oops;
347
348         s16b            keys;
349
350         s16b            last;
351
352         s16b            mapped;
353
354         s16b            rows;
355         s16b            cols;
356
357         s16b            font_id;
358         s16b            font_size;
359         s16b            font_face;
360         s16b            font_mono;
361
362         s16b            font_o_x;
363         s16b            font_o_y;
364         s16b            font_wid;
365         s16b            font_hgt;
366
367         s16b            tile_o_x;
368         s16b            tile_o_y;
369         s16b            tile_wid;
370         s16b            tile_hgt;
371
372         s16b            size_wid;
373         s16b            size_hgt;
374
375         s16b            size_ow1;
376         s16b            size_oh1;
377         s16b            size_ow2;
378         s16b            size_oh2;
379 };
380
381
382
383
384 /*
385  * Forward declare -- see below
386  */
387 static bool CheckEvents(bool wait);
388
389 #ifndef MACH_O_CARBON
390
391 /*
392  * Hack -- location of the main directory
393  */
394 static short app_vol;
395 static long  app_dir;
396
397 #endif /* !MACH_O_CARBON */
398
399 /*
400  * Delay handling of double-clicked savefiles
401  */
402 Boolean open_when_ready = FALSE;
403
404 /*
405  * Delay handling of pre-emptive "quit" event
406  */
407 Boolean quit_when_ready = FALSE;
408
409
410 /*
411  * Hack -- game in progress
412  */
413 static int game_in_progress = 0;
414
415
416 /*
417  * Only do "SetPort()" when needed
418  */
419 static WindowPtr active = NULL;
420
421
422
423 /*
424  * An array of term_data's
425  */
426 static term_data data[MAX_TERM_DATA];
427
428
429
430 /*
431  * Note when "open"/"new" become valid
432  */
433 static bool initialized = FALSE;
434
435 /*
436  * Version of Mac OS - for version specific bug workarounds (; ;)
437  */
438 static long mac_os_version;
439
440
441 #if defined(__MWERKS__)
442 /*
443  * CodeWarrior uses Universal Procedure Pointers
444  */
445 static ModalFilterUPP ynfilterUPP;
446
447 #endif /* __MWERKS__ */
448
449 #ifdef USE_SFL_CODE
450
451 /*
452  * Apple Event Hooks
453  */
454 AEEventHandlerUPP AEH_Start_UPP;
455 AEEventHandlerUPP AEH_Quit_UPP;
456 AEEventHandlerUPP AEH_Print_UPP;
457 AEEventHandlerUPP AEH_Open_UPP;
458
459 #endif
460
461 # ifdef USE_ASYNC_SOUND
462
463 /*
464  * Asynchronous sound player revised
465  */
466 #if defined(USE_QT_SOUND) && !defined(MACH_O_CARBON)
467 # undef USE_QT_SOUND
468 #endif /* USE_QT_SOUND && !MACH_O_CARBON */
469
470
471 /*
472  * Number of channels in the channel pool
473  */
474 #if TARGET_API_MAC_CARBON
475 #define MAX_CHANNELS            8
476 #else
477 #define MAX_CHANNELS            4
478 #endif
479
480 /*
481  * A pool of sound channels
482  */
483 static SndChannelPtr channels[MAX_CHANNELS];
484
485 /*
486  * Status of the channel pool
487  */
488 static Boolean channel_initialised = FALSE;
489
490 /*
491  * Data handles containing sound samples
492  */
493 static SndListHandle samples[SOUND_MAX];
494
495 /*
496  * Reference counts of sound samples
497  */
498 static SInt16 sample_refs[SOUND_MAX];
499
500
501 /*
502  * Sound effects
503  *
504  * These constants aren't used by the program at the moment.
505  */
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 % */
511
512 /* I'm just too lazy to write a panel for this XXX XXX */
513 static SInt16 sound_volume = SOUND_VOLUME_MAX;
514
515 #ifdef USE_QT_SOUND
516
517 /*
518  * Moving graphics resources into data fork -- pelpel
519  *
520  * (Carbon, Bundle)
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);
525  */
526 static Boolean get_resource_spec(
527         CFStringRef base_name, CFStringRef type_name, FSSpec *spec)
528 {
529         CFURLRef res_url;
530         FSRef ref;
531
532         /* Find resource (=file) in the current bundle */
533         res_url = CFBundleCopyResourceURL(
534                 CFBundleGetMainBundle(), base_name, type_name, NULL);
535
536         /* Oops */
537         if (res_url == NULL) return (false);
538
539         /* Convert CFURL to FSRef */
540         (void)CFURLGetFSRef(res_url, &ref);
541
542         /* Convert FSRef to FSSpec */
543         (void)FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
544
545         /* Free allocated CF data */
546         CFRelease(res_url);
547
548         /* Success */
549         return (true);
550 }
551
552 /*
553  * QuickTime sound, by Ron Anderson
554  *
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
558  */
559
560 /*
561  * (QuickTime)
562  * Load sound effects from data-fork resources.  They are wav files
563  * with the same names as angband_sound_name[] (variable.c)
564  *
565  * Globals referenced: angband_sound_name[]
566  * Globals updated: samples[] (they can be *huge*)
567  */
568 static void load_sounds(void)
569 {
570         OSErr err;
571         int i;
572
573         /* Start QuickTime */
574         err = EnterMovies();
575
576         /* Error */
577         if (err != noErr) return;
578
579         /*
580          * This loop may take a while depending on the count and size of samples
581          * to load.
582          *
583          * We should use a progress dialog for this.
584          */
585         for (i = 1; i < SOUND_MAX; i++)
586         {
587                 /* Apple APIs always give me headacke :( */
588                 CFStringRef name;
589                 FSSpec spec;
590                 SInt16 file_id;
591                 SInt16 res_id;
592                 Str255 movie_name;
593                 Movie movie;
594                 Track track;
595                 Handle h;
596                 Boolean res;
597
598                 /* Allocate CFString with the name of sound event to be processed */
599                 name = CFStringCreateWithCString(NULL, angband_sound_name[i],
600                         kTextEncodingUS_ASCII);
601
602                 /* Error */
603                 if (name == NULL) continue;
604
605                 /* Find sound sample resource with the same name */
606                 res = get_resource_spec(name, CFSTR("wav"), &spec);
607
608                 /* Free the reference to CFString */
609                 CFRelease(name);
610
611                 /* Error */
612                 if (!res) continue;
613
614                 /* Open the sound file */
615                 err = OpenMovieFile(&spec, &file_id, fsRdPerm);
616
617                 /* Error */
618                 if (err != noErr) continue;
619
620                 /* Create Movie from the file */
621                 err = NewMovieFromFile(&movie, file_id, &res_id, movie_name,
622                         newMovieActive, NULL);
623
624                 /* Error */
625                 if (err != noErr) goto close_file;
626
627                 /* Get the first track of the movie */
628                 track = GetMovieIndTrackType(movie, 1, AudioMediaCharacteristic,
629                         movieTrackCharacteristic | movieTrackEnabledOnly );
630
631                 /* Error */
632                 if (track == NULL) goto close_movie;
633
634                 /* Allocate a handle to store sample */
635                 h = NewHandle(0);
636
637                 /* Error */
638                 if (h == NULL) goto close_track;
639
640                 /* Dump the sample into the handle */
641                 err = PutMovieIntoTypedHandle(movie, track, soundListRsrc, h, 0,
642                         GetTrackDuration(track), 0L, NULL);
643
644                 /* Success */
645                 if (err == noErr)
646                 {
647                         /* Store the handle in the sample list */
648                         samples[i] = (SndListHandle)h;
649                 }
650
651                 /* Failure */
652                 else
653                 {
654                         /* Free unused handle */
655                         DisposeHandle(h);
656                 }
657
658                 /* Free the track */
659                 close_track: DisposeMovieTrack(track);
660
661                 /* Free the movie */
662                 close_movie: DisposeMovie(movie);
663
664                 /* Close the movie file */
665                 close_file: CloseMovieFile(file_id);
666         }
667
668         /* Stop QuickTime */
669         ExitMovies();
670 }
671
672 #else /* USE_QT_SOUND */
673
674 /*
675  * Return a handle of 'snd ' resource given Angband sound event number,
676  * or NULL if it isn't found.
677  *
678  * Globals referenced: angband_sound_name[] (variable.c)
679  */
680 static SndListHandle find_sound(int num)
681 {
682         Str255 sound;
683
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);
687
688         /* Obtain resource XXX XXX XXX */
689         return ((SndListHandle)GetNamedResource('snd ', sound));
690 }
691
692 #endif /* USE_QT_SOUND */
693
694
695 /*
696  * Clean up sound support - to be called when the game exits.
697  *
698  * Globals referenced: channels[], samples[], sample_refs[].
699  */
700 static void cleanup_sound(void)
701 {
702         int i;
703
704         /* No need to clean it up */
705         if (!channel_initialised) return;
706
707         /* Dispose channels */
708         for (i = 0; i < MAX_CHANNELS; i++)
709         {
710                 /* Drain sound commands and free the channel */
711                 SndDisposeChannel(channels[i], TRUE);
712         }
713
714         /* Free sound data */
715         for (i = 1; i < SOUND_MAX; i++)
716         {
717                 /* Still locked */
718                 if ((sample_refs[i] > 0) && (samples[i] != NULL))
719                 {
720                         /* Unlock it */
721                         HUnlock((Handle)samples[i]);
722                 }
723
724 #ifndef USE_QT_SOUND
725
726                 /* Release it */
727                 if (samples[i]) ReleaseResource((Handle)samples[i]);
728 #else
729
730                 /* Free handle */
731                 if (samples[i]) DisposeHandle((Handle)samples[i]);
732 #endif /* !USE_QT_SOUND */
733         }
734 }
735
736
737 /*
738  * Play sound effects asynchronously -- pelpel
739  *
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.
744  *
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.
750  *
751  * Globals referenced: channel_initialised, channels[], samples[],
752  *   sample_refs[].
753  * Globals updated: ditto.
754  */
755 static void play_sound(int num, SInt16 vol)
756 {
757         OSErr err;
758         int i;
759         int prev_num;
760         SndListHandle h;
761         SndChannelPtr chan;
762         SCStatus status;
763
764         static int next_chan;
765         static SInt16 channel_occupants[MAX_CHANNELS];
766         static SndCommand volume_cmd, quiet_cmd;
767
768
769         /* Initialise sound channels */
770         if (!channel_initialised)
771         {
772                 for (i = 0; i < MAX_CHANNELS; i++)
773                 {
774                         /* Paranoia - Clear occupant table */
775                         /* channel_occupants[i] = 0; */
776
777                         /* Create sound channel for all sounds to play from */
778                         err = SndNewChannel(&channels[i], sampledSynth, initMono, 0L);
779
780                         /* Error */
781                         if (err != noErr)
782                         {
783                                 /* Free channels */
784                                 while (--i >= 0)
785                                 {
786                                         SndDisposeChannel(channels[i], TRUE);
787                                 }
788
789                                 /* Notify error */
790 #ifdef JP
791                                 plog("¥µ¥¦¥ó¥É¥Á¥ã¥ó¥Í¥ë¤ò½é´ü²½½ÐÍè¤Þ¤»¤ó!");
792 #else
793                                 plog("Cannot initialise sound channels!");
794 #endif
795
796                                 /* Cancel request */
797                                 use_sound = arg_sound = FALSE;
798
799                                 /* Failure */
800                                 return;
801                         }
802                 }
803
804                 /* First channel to use */
805                 next_chan = 0;
806
807                 /* Prepare volume command */
808                 volume_cmd.cmd = volumeCmd;
809                 volume_cmd.param1 = 0;
810                 volume_cmd.param2 = 0;
811
812                 /* Prepare quiet command */
813                 quiet_cmd.cmd = quietCmd;
814                 quiet_cmd.param1 = 0;
815                 quiet_cmd.param2 = 0;
816
817                 /* Initialisation complete */
818                 channel_initialised = TRUE;
819         }
820
821         /* Paranoia */
822         if ((num <= 0) || (num >= SOUND_MAX)) return;
823
824         /* Prepare volume command */
825         volume_cmd.param2 = ((SInt32)vol << 16) | vol;
826
827         /* Channel to use (round robin) */
828         chan = channels[next_chan];
829
830         /* See if the resource is already in use */
831         if (sample_refs[num] > 0)
832         {
833                 /* Resource in use */
834                 h = samples[num];
835
836                 /* Increase the refcount */
837                 sample_refs[num]++;
838         }
839
840         /* Sound is not currently in use */
841         else
842         {
843                 /* Get handle for the sound */
844 #ifdef USE_QT_SOUND
845                 h = samples[num];
846 #else
847                 h = find_sound(num);
848 #endif /* USE_QT_SOUND */
849
850                 /* Sample not available */
851                 if (h == NULL) return;
852
853 #ifndef USE_QT_SOUND
854
855                 /* Load resource */
856                 LoadResource((Handle)h);
857
858                 /* Remember it */
859                 samples[num] = h;
860
861 #endif /* !USE_QT_SOUND */
862
863                 /* Lock the handle */
864                 HLockHi((Handle)h);
865
866                 /* Initialise refcount */
867                 sample_refs[num] = 1;
868         }
869
870         /* Poll the channel */
871         err = SndChannelStatus(chan, sizeof(SCStatus), &status);
872
873         /* It isn't available */
874         if ((err != noErr) || status.scChannelBusy)
875         {
876                 /* Shut it down */
877                 SndDoImmediate(chan, &quiet_cmd);
878         }
879
880         /* Previously played sound on this channel */
881         prev_num = channel_occupants[next_chan];
882
883         /* Process previously played sound */
884         if (prev_num != 0)
885         {
886                 /* Decrease refcount */
887                 sample_refs[prev_num]--;
888
889                 /* We can free it now */
890                 if (sample_refs[prev_num] <= 0)
891                 {
892                         /* Unlock */
893                         HUnlock((Handle)samples[prev_num]);
894
895 #ifndef USE_QT_SOUND
896
897                         /* Release */
898                         ReleaseResource((Handle)samples[prev_num]);
899
900                         /* Forget handle */
901                         samples[prev_num] = NULL;
902
903 #endif /* !USE_QT_SOUND */
904
905                         /* Paranoia */
906                         sample_refs[prev_num] = 0;
907                 }
908         }
909
910         /* Remember this sound as the current occupant of the channel */
911         channel_occupants[next_chan] = num;
912
913         /* Set up volume for channel */
914         SndDoImmediate(chan, &volume_cmd);
915
916         /* Play new sound asynchronously */
917         SndPlay(chan, h, TRUE);
918
919         /* Schedule next channel (round robin) */
920         next_chan++;
921         if (next_chan >= MAX_CHANNELS) next_chan = 0;
922 }
923
924 # else /* USE_ASYNC_SOUND */
925
926 /*
927  * Play sound synchronously
928  *
929  * This may not be your choice, but much safer and much less resource hungry.
930  */
931 static void play_sound(int num, SInt16 vol)
932 {
933         Handle handle;
934         Str255 sound;
935
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);
939
940         /* Obtain resource XXX XXX XXX */
941         handle = GetNamedResource('snd ', sound);
942
943         /* Oops */
944         if (handle == NULL) return;
945
946         /* Load and Lock */
947         LoadResource(handle);
948         HLockHi(handle);
949
950         /* Play sound (wait for completion) */
951         SndPlay(NULL, (SndListHandle)handle, FALSE);
952
953         /* Unlock and release */
954         HUnlock(handle);
955         ReleaseResource(handle);
956 }
957
958 # endif /* USE_ASYNC_SOUND */
959
960 #ifndef MACH_O_CARBON
961
962 /*
963         Extra Sound Mode
964 */
965
966 static int ext_sound = 0;
967
968 #define         SND_NON         0
969 #define         SND_ATTACK      1
970 #define         SND_MOVE                2
971 #define         SND_TRAP                3
972 #define         SND_SHOP                4
973 #define         SND_ME          5
974 #define         SND_CMD_ERROR   6
975
976 static int soundchoice[] = {
977         SND_NON,
978         SND_ATTACK,
979         SND_ATTACK,
980         SND_ATTACK,
981         SND_TRAP,
982         SND_ATTACK,
983         SND_ME,
984         SND_ME,
985         SND_ME,
986         SND_MOVE,
987         SND_ATTACK,
988         SND_ME,
989         SND_ATTACK,
990         SND_NON,
991         SND_MOVE,
992         SND_MOVE,
993         SND_ME,
994         SND_SHOP,
995         SND_SHOP,
996         SND_SHOP,
997         SND_SHOP,
998         SND_MOVE,
999         SND_MOVE,
1000         SND_MOVE,
1001         SND_MOVE,
1002         SND_ATTACK,
1003         SND_SHOP,
1004         SND_SHOP,
1005         SND_ME,
1006         SND_NON,
1007         SND_ATTACK,
1008         SND_NON,
1009         SND_NON,
1010         SND_NON,
1011         SND_NON,
1012         SND_ATTACK,
1013         SND_ATTACK,
1014         SND_NON,
1015         SND_NON,
1016         SND_ATTACK,
1017         SND_NON,
1018         SND_NON,
1019         SND_NON,
1020         SND_TRAP,
1021         SND_ATTACK,
1022         SND_ATTACK,
1023         SND_ATTACK,
1024         SND_ATTACK,
1025         SND_ATTACK,
1026         SND_NON,
1027         SND_NON,
1028         SND_NON,
1029         SND_NON,
1030         SND_NON,
1031         SND_CMD_ERROR,
1032         SND_TRAP,
1033         SND_NON,
1034         SND_NON,
1035         SND_TRAP,
1036         SND_ATTACK,
1037         SND_TRAP,
1038         SND_ATTACK,
1039         SND_ATTACK,
1040         SND_NON,
1041         SND_TRAP,
1042 };
1043
1044 static int ext_graf = 0;
1045
1046 #endif /* !MACH_O_CARBON */
1047
1048 static short                    soundmode[8];
1049
1050
1051 /*
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
1055  */
1056 #if TARGET_API_MAC_CARBON
1057 static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname)
1058 {
1059         CInfoPBRec pb;
1060         int err;
1061         int i, j;
1062
1063         char res[1000];
1064         
1065         FSSpec spec;
1066         short   vref;
1067     long        dirID;
1068     
1069         i=999;
1070
1071         res[i]=0; i--;
1072         for (j=1; j<=fname[0]; j++)
1073         {
1074                 res[i-fname[0]+j] = fname[j];
1075         }
1076         i-=fname[0];
1077
1078         vref = vrefnum;
1079         dirID = refnum;
1080
1081         while (1)
1082         {
1083                 pb.dirInfo.ioDrDirID=pb.dirInfo.ioDrParID;
1084                 err = FSMakeFSSpec( vref, dirID, "\p", &spec );
1085                 
1086                 if( err != noErr )
1087                     break;
1088                 
1089                 res[i] = ':'; i--;
1090                 for (j=1; j<=spec.name[0]; j++)
1091                 {
1092                         res[i-spec.name[0]+j] = spec.name[j];
1093                 }
1094                 i -= spec.name[0];
1095                 
1096                 dirID = spec.parID;
1097         }
1098
1099         /* Extract the result */
1100         for (j = 0, i++; res[i]; j++, i++) buf[j] = res[i];
1101         buf[j] = 0;
1102 }
1103 #else
1104 static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname)
1105 {
1106         DirInfo pb;
1107         Str255 name;
1108         int err;
1109         int i, j;
1110
1111         char res[1000];
1112
1113         i=999;
1114
1115         res[i]=0; i--;
1116         for (j=1; j<=fname[0]; j++)
1117         {
1118                 res[i-fname[0]+j] = fname[j];
1119         }
1120         i-=fname[0];
1121
1122         pb.ioCompletion=NULL;
1123         pb.ioNamePtr=name;
1124         pb.ioVRefNum=vrefnum;
1125         pb.ioDrParID=refnum;
1126         pb.ioFDirIndex=-1;
1127
1128         while (1)
1129         {
1130                 pb.ioDrDirID=pb.ioDrParID;
1131                 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
1132                 res[i] = ':'; i--;
1133                 for (j=1; j<=name[0]; j++)
1134                 {
1135                         res[i-name[0]+j] = name[j];
1136                 }
1137                 i -= name[0];
1138
1139                 if (pb.ioDrDirID == fsRtDirID) break;
1140         }
1141
1142         /* Extract the result */
1143         for (j = 0, i++; res[i]; j++, i++) buf[j] = res[i];
1144         buf[j] = 0;
1145 }
1146 #endif
1147
1148 #if TARGET_API_MAC_CARBON
1149 pascal OSErr FSpLocationFromFullPath(short fullPathLength,
1150                                                                          const void *fullPath,
1151                                                                          FSSpec *spec)
1152 {
1153         AliasHandle     alias;
1154         OSErr           result;
1155         Boolean         wasChanged;
1156         Str32           nullString;
1157         
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 )
1162         {
1163                 /* Let the Alias Manager resolve the alias. */
1164                 result = ResolveAlias(NULL, alias, spec, &wasChanged);
1165                 
1166                 /* work around Alias Mgr sloppy volume matching bug */
1167                 if ( spec->vRefNum == 0 )
1168                 {
1169                         /* invalidate wrong FSSpec */
1170                         spec->parID = 0;
1171                         spec->name[0] =  0;
1172                         result = nsvErr;
1173                 }
1174                 DisposeHandle((Handle)alias);   /* Free up memory used */
1175         }
1176         return ( result );
1177 }
1178 #endif
1179
1180 #if 0
1181
1182 /*
1183  * XXX XXX XXX Allow the system to ask us for a filename
1184  */
1185 static bool askfor_file(char *buf, int len)
1186 {
1187         SFReply reply;
1188         Str255 dflt;
1189         Point topleft;
1190         short vrefnum;
1191         long drefnum, junk;
1192
1193         /* Default file name */
1194         sprintf((char*)dflt + 1, "%s's description", buf);
1195         dflt[0] = strlen((char*)dflt + 1);
1196
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); */
1202
1203         /* Process */
1204         if (reply.good)
1205         {
1206                 int fc;
1207
1208                 /* Get info */
1209                 GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
1210
1211                 /* Extract the name */
1212                 refnum_to_name(buf, drefnum, vrefnum, (char*)reply.fName);
1213
1214                 /* Success */
1215                 return (TRUE);
1216         }
1217
1218         /* Failure */
1219         return (FALSE);
1220 }
1221
1222 #endif
1223
1224 #if !TARGET_API_MAC_CARBON
1225 static void local_to_global( Rect *r )
1226 {
1227         Point           temp;
1228         
1229         temp.h = r->left;
1230         temp.v = r->top;
1231         
1232         LocalToGlobal( &temp );
1233         
1234         r->left = temp.h;
1235         r->top = temp.v;
1236         
1237         temp.h = r->right;
1238         temp.v = r->bottom;
1239         
1240         LocalToGlobal( &temp );
1241         
1242         r->right = temp.h;
1243         r->bottom = temp.v;
1244 }
1245 #endif /* !TARGET_API_MAC_CARBON */
1246
1247 static void global_to_local( Rect *r )
1248 {
1249         Point           temp;
1250         
1251         temp.h = r->left;
1252         temp.v = r->top;
1253         
1254         GlobalToLocal( &temp );
1255         
1256         r->left = temp.h;
1257         r->top = temp.v;
1258         
1259         temp.h = r->right;
1260         temp.v = r->bottom;
1261         
1262         GlobalToLocal( &temp );
1263         
1264         r->right = temp.h;
1265         r->bottom = temp.v;
1266 }
1267
1268
1269 #ifdef MAC_MPW
1270
1271 /*
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
1276  */
1277 void convert_pathname(char* path)
1278 {
1279         char buf[1024];
1280
1281         /* Nothing has to be done for CarbonLib on Classic */
1282         if (mac_os_version >= 0x1000)
1283         {
1284                 /* Convert to POSIX style */
1285                 ConvertHFSPathToUnixPath(path, buf);
1286
1287                 /* Copy the result back */
1288                 strcpy(path, buf);
1289         }
1290
1291         /* Done. */
1292         return;
1293 }
1294
1295 # ifdef CHECK_MODIFICATION_TIME
1296
1297 /*
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.
1300  */
1301 static int get_modification_time(cptr path, u32b *mod_time)
1302 {
1303         CInfoPBRec pb;
1304         Str255 pathname;
1305         int i;
1306
1307         /* Paranoia - make sure the pathname fits in Str255 */
1308         i = strlen(path);
1309         if (i > 255) return (-1);
1310
1311         /* Convert pathname to a Pascal string */
1312         strncpy((char *)pathname + 1, path, 255);
1313         pathname[0] = i;
1314
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;
1320
1321         /* Get catalog information of the file */
1322         if (PBGetCatInfoSync(&pb) != noErr) return (-1);
1323
1324         /* Set modification date and time */
1325         *mod_time = pb.hFileInfo.ioFlMdDat;
1326
1327         /* Success */
1328         return (0);
1329 }
1330
1331
1332 /*
1333  * A (non-Mach-O) Mac OS version of check_modification_time, for those
1334  * compilers without good enough POSIX-compatibility libraries XXX XXX
1335  */
1336 errr check_modification_date(int fd, cptr template_file)
1337 {
1338 #pragma unused(fd)
1339         u32b txt_stat, raw_stat;
1340         char *p;
1341         char fname[32];
1342         char buf[1024];
1343
1344         /* Build the file name */
1345         path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, template_file);
1346
1347         /* XXX XXX XXX */
1348         convert_pathname(buf);
1349
1350         /* Obtain modification time */
1351         if (get_modification_time(buf, &txt_stat)) return (-1);
1352
1353         /* XXX Build filename of the corresponding *.raw file */
1354         strnfmt(fname, sizeof(fname), "%s", template_file);
1355
1356         /* Find last '.' */
1357         p = strrchr(fname, '.');
1358
1359         /* Can't happen */
1360         if (p == NULL) return (-1);
1361
1362         /* Substitute ".raw" for ".txt" */
1363         strcpy(p, ".raw");
1364
1365         /* Build the file name of the raw file */
1366         path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, fname);
1367
1368         /* XXX XXX XXX */
1369         convert_pathname(buf);
1370
1371         /* Obtain modification time */
1372         if (get_modification_time(buf, &raw_stat)) return (-1);
1373
1374         /* Ensure the text file is not newer than the raw file */
1375         if (txt_stat > raw_stat) return (-1);
1376
1377         /* Keep using the current .raw file */
1378         return (0);
1379 }
1380
1381 # endif /* CHECK_MODIFICATION_TIME */
1382
1383 #endif /* MAC_MPW */
1384
1385 /*
1386  * Center a rectangle inside another rectangle
1387  */
1388 static void center_rect(Rect *r, Rect *s)
1389 {
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;
1394         r->left += dx;
1395         r->right += dx;
1396         r->top += dy;
1397         r->bottom += dy;
1398 }
1399
1400
1401 #ifdef MACH_O_CARBON
1402
1403 /* Carbon File Manager utilities by pelpel */
1404
1405 /*
1406  * (Carbon)
1407  * Convert a pathname to a corresponding FSSpec.
1408  * Returns noErr on success.
1409  */
1410 static OSErr path_to_spec(const char *path, FSSpec *spec)
1411 {
1412         OSErr err;
1413         FSRef ref;
1414
1415         /* Convert pathname to FSRef ... */
1416         err = FSPathMakeRef(path, &ref, NULL);
1417         if (err != noErr) return (err);
1418
1419         /* ... then FSRef to FSSpec */
1420         err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
1421         
1422         /* Inform caller of success or failure */
1423         return (err);
1424 }
1425
1426
1427 /*
1428  * (Carbon)
1429  * Convert a FSSpec to a corresponding pathname.
1430  * Returns noErr on success.
1431  */
1432 static OSErr spec_to_path(const FSSpec *spec, char *buf, size_t size)
1433 {
1434         OSErr err;
1435         FSRef ref;
1436
1437         /* Convert FSSpec to FSRef ... */
1438         err = FSpMakeFSRef(spec, &ref);
1439         if (err != noErr) return (err);
1440
1441         /* ... then FSRef to pathname */
1442         err = FSRefMakePath(&ref, buf, size);
1443
1444         /* Inform caller of success or failure */
1445         return (err);
1446 }
1447
1448
1449 /*
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.
1453  */
1454 void fsetfileinfo(cptr pathname, OSType fcreator, OSType ftype)
1455 {
1456         OSErr err;
1457         FSSpec spec;
1458         FInfo info;
1459
1460         /* Convert pathname to FSSpec */
1461         if (path_to_spec(pathname, &spec) != noErr) return;
1462
1463         /* Obtain current finder info of the file */
1464         if (FSpGetFInfo(&spec, &info) != noErr) return;
1465
1466         /* Overwrite creator and type */
1467         info.fdCreator = fcreator;
1468         info.fdType = ftype;
1469         err = FSpSetFInfo(&spec, &info);
1470
1471         /* Done */
1472         return;
1473 }
1474
1475
1476 #else /* MACH_O_CARBON */
1477
1478
1479 /*
1480  * Convert a pascal string in place
1481  *
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.
1485  */
1486 static void ptocstr(StringPtr src)
1487 {
1488         int i;
1489
1490         /* Hack -- pointer */
1491         char *s = (char*)(src);
1492
1493         /* Hack -- convert the string */
1494         for (i = s[0]; i; i--, s++) s[0] = s[1];
1495
1496         /* Hack -- terminate the string */
1497         s[0] = '\0';
1498 }
1499
1500
1501 #if defined(USE_SFL_CODE)
1502
1503
1504 /*
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
1509  * is.
1510  *
1511  * I had to hack PathNameFromDirID a little for MetroWerks, but it's awfully
1512  * nice.
1513  */
1514 static void pstrcat(StringPtr dst, StringPtr src)
1515 {
1516         /* copy string in */
1517         BlockMove(src + 1, dst + *dst + 1, *src);
1518
1519         /* adjust length byte */
1520         *dst += *src;
1521 }
1522
1523 /*
1524  * pstrinsert - insert string 'src' at beginning of string 'dst'
1525  */
1526 static void pstrinsert(StringPtr dst, StringPtr src)
1527 {
1528         /* make room for new string */
1529         BlockMove(dst + 1, dst + *src + 1, *dst);
1530
1531         /* copy new string in */
1532         BlockMove(src + 1, dst + 1, *src);
1533
1534         /* adjust length byte */
1535         *dst += *src;
1536 }
1537
1538 static void PathNameFromDirID(long dirID, short vRefNum, StringPtr fullPathName)
1539 {
1540         CInfoPBRec      block;
1541         Str255  directoryName;
1542         OSErr   err;
1543
1544         fullPathName[0] = '\0';
1545
1546         block.dirInfo.ioDrParID = dirID;
1547         block.dirInfo.ioNamePtr = directoryName;
1548
1549         while (1)
1550         {
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;
1558         }
1559 }
1560
1561 #endif
1562 #endif /* MACH_O_CARBON */
1563
1564 /*
1565  * Activate a given window, if necessary
1566  */
1567 static void activate(WindowPtr w)
1568 {
1569         /* Activate */
1570         if (active != w)
1571         {
1572                 /* Activate */
1573 #if TARGET_API_MAC_CARBON
1574                 if (w) SetPortWindowPort(w);
1575 #else
1576                 if (w) SetPort(w);
1577 #endif
1578
1579                 /* Remember */
1580                 active = w;
1581         }
1582 }
1583
1584
1585 /*
1586  * Display a warning message
1587  */
1588 static void mac_warning(cptr warning)
1589 {
1590         Str255 text;
1591         int len, i;
1592
1593         /* Limit of 250 chars */
1594         len = strlen(warning);
1595         if (len > 250) len = 250;
1596
1597         /* Make a "Pascal" string */
1598         text[0] = len;
1599         for (i=0; i<len; i++) text[i+1] = warning[i];
1600
1601         /* Prepare the dialog box values */
1602         ParamText(text, "\p", "\p", "\p");
1603
1604         /* Display the Alert, wait for Okay */
1605         Alert(129, 0L);
1606 }
1607
1608
1609
1610 /*** Some generic functions ***/
1611
1612
1613 #ifdef ANGBAND_LITE_MAC
1614
1615 /*
1616  * Hack -- activate a color (0 to 255)
1617  */
1618 #define term_data_color(TD,A) /* Nothing */
1619
1620 #else /* ANGBAND_LITE_MAC */
1621
1622 /*
1623  * Hack -- activate a color (0 to 255)
1624  */
1625 static void term_data_color(term_data *td, int a)
1626 {
1627         u16b rv, gv, bv;
1628
1629         RGBColor color;
1630
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];
1635
1636         /* Set the color */
1637         color.red = (rv | (rv << 8));
1638         color.green = (gv | (gv << 8));
1639         color.blue = (bv | (bv << 8));
1640
1641         /* Activate the color */
1642         RGBForeColor(&color);
1643
1644         /* Memorize color */
1645         td->last = a;
1646 }
1647
1648 #endif /* ANGBAND_LITE_MAC */
1649
1650
1651 /*
1652  * Hack -- Apply and Verify the "font" info
1653  *
1654  * This should usually be followed by "term_data_check_size()"
1655  */
1656 static void term_data_check_font(term_data *td)
1657 {
1658         int i;
1659
1660         FontInfo info;
1661
1662         WindowPtr old = active;
1663
1664
1665         /* Activate */
1666         activate(td->w);
1667
1668         /* Instantiate font */
1669         TextFont(td->font_id);
1670         TextSize(td->font_size);
1671         TextFace(td->font_face);
1672
1673         /* Extract the font info */
1674         GetFontInfo(&info);
1675
1676         /* Assume monospaced */
1677         td->font_mono = TRUE;
1678
1679         /* Extract the font sizing values XXX XXX XXX */
1680         td->font_wid = CharWidth('@'); /* info.widMax; */
1681         td->font_hgt = info.ascent + info.descent;
1682         td->font_o_x = 0;
1683         td->font_o_y = info.ascent;
1684
1685         /* Check important characters */
1686         for (i = 33; i < 127; i++)
1687         {
1688                 /* Hack -- notice non-mono-space */
1689                 if (td->font_wid != CharWidth(i)) td->font_mono = FALSE;
1690
1691                 /* Hack -- collect largest width */
1692                 if (td->font_wid < CharWidth(i)) td->font_wid = CharWidth(i);
1693         }
1694
1695         /* Set default offsets */
1696         td->tile_o_x = td->font_o_x;
1697         td->tile_o_y = td->font_o_y;
1698
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;
1703         }
1704
1705         /* Re-activate the old window */
1706         activate(old);
1707 }
1708
1709
1710 /*
1711  * Hack -- Apply and Verify the "size" info
1712  */
1713 static void term_data_check_size(term_data *td)
1714 {
1715         BitMap          screen;
1716         
1717 #if TARGET_API_MAC_CARBON
1718         GetQDGlobalsScreenBits( &screen );
1719 #else
1720         screen = qd.screenBits;
1721 #endif
1722         /* Minimal window size */
1723         if (td == &data[0])
1724         {
1725                 /* Enforce minimal size */
1726                 if (td->cols < 80) td->cols = 80;
1727                 if (td->rows < 24) td->rows = 24;
1728         }
1729
1730         /* Allow small windows for the rest */
1731         else
1732         {
1733                 if (td->cols < 1) td->cols = 1;
1734                 if (td->rows < 1) td->rows = 1;
1735         }
1736
1737         /* Minimal tile size */
1738         if (td->tile_wid < 4) td->tile_wid = 4;
1739         if (td->tile_hgt < 4) td->tile_hgt = 4;
1740
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;
1744
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;
1748
1749         /* Apply font offsets */
1750         td->tile_o_x += td->font_o_x;
1751         td->tile_o_y += td->font_o_y;
1752
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;
1756
1757         /* Verify the top */
1758         if (td->r.top > screen.bounds.bottom - td->size_hgt)
1759         {
1760                 td->r.top = screen.bounds.bottom - td->size_hgt;
1761         }
1762
1763         /* Verify the top */
1764         if (td->r.top < screen.bounds.top + 30)
1765         {
1766                 td->r.top = screen.bounds.top + 30;
1767         }
1768
1769         /* Verify the left */
1770         if (td->r.left > screen.bounds.right - td->size_wid)
1771         {
1772                 td->r.left = screen.bounds.right - td->size_wid;
1773         }
1774
1775         /* Verify the left */
1776         if (td->r.left < screen.bounds.left)
1777         {
1778                 td->r.left = screen.bounds.left;
1779         }
1780
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;
1784
1785         /* Assume no graphics */
1786         td->t->higher_pict = FALSE;
1787         td->t->always_pict = FALSE;
1788
1789 #ifdef ANGBAND_LITE_MAC
1790
1791         /* No graphics */
1792
1793 #else /* ANGBAND_LITE_MAC */
1794
1795         /* Handle graphics */
1796         if (use_graphics)
1797         {
1798                 /* Use higher_pict whenever possible */
1799                 if (td->font_mono) td->t->higher_pict = TRUE;
1800
1801                 /* Use always_pict only when necessary */
1802                 else td->t->always_pict = TRUE;
1803         }
1804
1805 #endif /* ANGBAND_LITE_MAC */
1806
1807         /* Fake mono-space */
1808         if (!td->font_mono ||
1809             (td->font_wid != td->tile_wid) ||
1810                 (td->font_hgt != td->tile_hgt))
1811         {
1812                 /* Handle fake monospace -- this is SLOW */
1813                 if (td->t->higher_pict) td->t->higher_pict = FALSE;
1814                 td->t->always_pict = TRUE;
1815         }
1816 }
1817
1818 /*
1819  * Hack -- resize a term_data
1820  *
1821  * This should normally be followed by "term_data_resize()"
1822  */
1823 static void term_data_resize(term_data *td)
1824 {
1825         /* Actually resize the window */
1826         SizeWindow(td->w, td->size_wid, td->size_hgt, 0);
1827 }
1828
1829
1830
1831 /*
1832  * Hack -- redraw a term_data
1833  *
1834  * Note that "Term_redraw()" calls "TERM_XTRA_CLEAR"
1835  */
1836 static void term_data_redraw(term_data *td)
1837 {
1838         term *old = Term;
1839
1840         /* Activate the term */
1841         Term_activate(td->t);
1842
1843         /* Redraw the contents */
1844         Term_redraw();
1845
1846         /* Flush the output */
1847         Term_fresh();
1848
1849         /* Restore the old term */
1850         Term_activate(old);
1851         
1852         /* No need to redraw */
1853 #if TARGET_API_MAC_CARBON
1854         {
1855                 RgnHandle               theRgn = NewRgn();
1856                 GetWindowRegion( td->w, kWindowContentRgn, theRgn );
1857                 ValidWindowRgn( (WindowRef)(td->w), theRgn );
1858                 DisposeRgn( theRgn );
1859         }
1860 #else
1861         ValidRect(&td->w->portRect);
1862 #endif
1863
1864 }
1865
1866
1867
1868
1869 #ifdef ANGBAND_LITE_MAC
1870
1871 /* No graphics */
1872
1873 #else /* ANGBAND_LITE_MAC */
1874
1875
1876 /*
1877  * Constants
1878  */
1879
1880 static int pictID = 1001;       /* 8x8 tiles; 16x16 tiles are 1002 */
1881
1882 static int grafWidth = 8;       /* Always equal to grafHeight */
1883 static int grafHeight = 8;      /* Either 8 or 16 */
1884
1885 static bool arg_newstyle_graphics;
1886 static bool use_newstyle_graphics;
1887
1888 /*
1889  * Forward Declare
1890  */
1891 typedef struct FrameRec FrameRec;
1892
1893 /*
1894  * Frame
1895  *
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)
1899  */
1900 struct FrameRec
1901 {
1902         GWorldPtr               framePort;
1903         PixMapHandle    framePixHndl;
1904         PixMapPtr               framePix;
1905         
1906 };
1907
1908
1909 /*
1910  * The global picture data
1911  */
1912 static FrameRec *frameP = NULL;
1913
1914
1915 /*
1916  * Lock a frame
1917  */
1918 static void BenSWLockFrame(FrameRec *srcFrameP)
1919 {
1920         PixMapHandle            pixMapH;
1921
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;
1928 #else
1929         srcFrameP->framePix = (PixMapPtr)StripAddress(*(Handle)pixMapH);
1930 #endif
1931         
1932 }
1933
1934
1935 /*
1936  * Unlock a frame
1937  */
1938 static void BenSWUnlockFrame(FrameRec *srcFrameP)
1939 {
1940         if (srcFrameP->framePort != NULL)
1941         {
1942                 HUnlock((Handle)srcFrameP->framePixHndl);
1943                 UnlockPixels(srcFrameP->framePixHndl);
1944         }
1945
1946         srcFrameP->framePix = NULL;
1947         
1948 }
1949
1950 static OSErr BenSWCreateGWorldFromPict(
1951         GWorldPtr *pictGWorld,
1952         PicHandle pictH)
1953 {
1954         OSErr err;
1955         GWorldPtr saveGWorld;
1956         GDHandle saveGDevice;
1957         GWorldPtr tempGWorld;
1958         Rect pictRect;
1959         short depth;
1960         GDHandle theGDH;
1961
1962         /* Reset */
1963         *pictGWorld = NULL;
1964
1965         /* Get depth */
1966         depth = data[0].pixelDepth;
1967
1968         /* Get GDH */
1969         theGDH = data[0].theGDH;
1970
1971         /* Obtain size rectangle */
1972         pictRect = (**pictH).picFrame;
1973         OffsetRect(&pictRect, -pictRect.left, -pictRect.top);
1974
1975         /* Create a GWorld */
1976         err = NewGWorld(&tempGWorld, depth, &pictRect, nil, 
1977                                         theGDH, noNewDevice);
1978
1979         /* Success */
1980         if (err != noErr)
1981         {
1982                 return (err);
1983         }
1984
1985         /* Save pointer */
1986         *pictGWorld = tempGWorld;
1987
1988         /* Save GWorld */
1989         GetGWorld(&saveGWorld, &saveGDevice);
1990
1991         /* Activate */
1992         SetGWorld(tempGWorld, nil);
1993
1994         /* Dump the pict into the GWorld */
1995         (void)LockPixels(GetGWorldPixMap(tempGWorld));
1996         EraseRect(&pictRect);
1997         DrawPicture(pictH, &pictRect);
1998         UnlockPixels(GetGWorldPixMap(tempGWorld));
1999
2000         /* Restore GWorld */
2001         SetGWorld(saveGWorld, saveGDevice);
2002         
2003         /* Success */
2004         return (0);
2005 }
2006
2007
2008
2009
2010 /*
2011  * Init the global "frameP"
2012  */
2013
2014 static errr globe_init(void)
2015 {
2016         OSErr err;
2017         
2018         GWorldPtr tempPictGWorldP;
2019
2020         PicHandle newPictH;
2021
2022         /* Use window XXX XXX XXX */
2023 #if TARGET_API_MAC_CARBON
2024         SetPortWindowPort(data[0].w);
2025 #else
2026         SetPort(data[0].w);
2027 #endif
2028
2029
2030         /* Get the pict resource */
2031         newPictH = GetPicture(pictID);
2032
2033         /* Analyze result */
2034         err = (newPictH ? 0 : -1);
2035
2036         /* Oops */
2037         if (err == noErr)
2038         {
2039
2040                 /* Create GWorld */
2041                 err = BenSWCreateGWorldFromPict(&tempPictGWorldP, newPictH);
2042                 
2043                 /* Release resource */
2044                 ReleaseResource((Handle)newPictH);
2045
2046                 /* Error */
2047                 if (err == noErr)
2048                 {
2049                         /* Create the frame */
2050                         frameP = (FrameRec*)NewPtrClear((Size)sizeof(FrameRec));
2051
2052                         /* Analyze result */
2053                         err = (frameP ? 0 : -1);
2054
2055                         /* Oops */
2056                         if (err == noErr)
2057                         {
2058                                 /* Save GWorld */
2059                                 frameP->framePort = tempPictGWorldP;
2060
2061                                 /* Lock it */
2062                                 BenSWLockFrame(frameP);
2063                         }
2064                 }
2065         }
2066
2067         /* Result */
2068         return (err);
2069 }
2070
2071
2072 /*
2073  * Nuke the global "frameP"
2074  */
2075 static errr globe_nuke(void)
2076 {
2077         /* Dispose */
2078         if (frameP)
2079         {
2080                 /* Unlock */
2081                 BenSWUnlockFrame(frameP);
2082
2083                 /* Dispose of the GWorld */
2084                 DisposeGWorld(frameP->framePort);
2085
2086                 /* Dispose of the memory */
2087                 DisposePtr((Ptr)frameP);
2088
2089                 /* Forget */
2090                 frameP = NULL;
2091         }
2092
2093         /* Flush events */      
2094         FlushEvents(everyEvent, 0);
2095
2096         /* Success */
2097         return (0);
2098 }
2099
2100
2101 #endif /* ANGBAND_LITE_MAC */
2102
2103
2104
2105 /*** Support for the "z-term.c" package ***/
2106
2107
2108 /*
2109  * Initialize a new Term
2110  *
2111  * Note also the "window type" called "noGrowDocProc", which might be more
2112  * appropriate for the main "screen" window.
2113  *
2114  * Note the use of "srcCopy" mode for optimized screen writes.
2115  */
2116 static void Term_init_mac(term *t)
2117 {
2118         term_data *td = (term_data*)(t->data);
2119
2120         static RGBColor black = {0x0000,0x0000,0x0000};
2121         static RGBColor white = {0xFFFF,0xFFFF,0xFFFF};
2122
2123 #ifdef ANGBAND_LITE_MAC
2124
2125         /* Make the window */
2126         td->w = NewWindow(0, &td->r, td->title, 0, noGrowDocProc, (WindowPtr)-1, 1, 0L);
2127
2128 #else /* ANGBAND_LITE_MAC */
2129
2130         /* Make the window */
2131         td->w = NewCWindow(0, &td->r, td->title, 0, documentProc, (WindowPtr)-1, 1, 0L);
2132
2133 #endif /* ANGBAND_LITE_MAC */
2134
2135         /* Activate the window */
2136         activate(td->w);
2137
2138         /* Erase behind words */
2139         TextMode(srcCopy);
2140
2141         /* Apply and Verify */
2142         term_data_check_font(td);
2143         term_data_check_size(td);
2144
2145         /* Resize the window */
2146         term_data_resize(td);
2147
2148 #ifdef ANGBAND_LITE_MAC
2149
2150         /* Prepare the colors (base colors) */
2151         BackColor(blackColor);
2152         ForeColor(whiteColor);
2153
2154 #else /* ANGBAND_LITE_MAC */
2155
2156         /* Prepare the colors (real colors) */
2157         RGBBackColor(&black);
2158         RGBForeColor(&white);
2159
2160         /* Block */
2161         {
2162                 Rect globalRect;
2163                 GDHandle mainGDH;
2164                 GDHandle currentGDH;
2165                 GWorldPtr windowGWorld;
2166                 PixMapHandle basePixMap;
2167
2168                 /* Obtain the rect */
2169 #if TARGET_API_MAC_CARBON
2170                 GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &globalRect );
2171 #else
2172                 globalRect = td->w->portRect;
2173                 LocalToGlobal((Point*)&globalRect.top);
2174                 LocalToGlobal((Point*)&globalRect.bottom);
2175 #endif
2176
2177                 /* Obtain the proper GDH */
2178                 mainGDH = GetMaxDevice(&globalRect);
2179
2180                 /* Extract GWorld and GDH */
2181                 GetGWorld(&windowGWorld, &currentGDH);
2182
2183                 /* Obtain base pixmap */
2184                 basePixMap = (**mainGDH).gdPMap;
2185
2186                 /* Save pixel depth */
2187                 td->pixelDepth = (**basePixMap).pixelSize;
2188
2189                 /* Save Window GWorld */
2190                 td->theGWorld = windowGWorld;
2191
2192                 /* Save Window GDH */
2193                 td->theGDH = currentGDH;
2194
2195                 /* Save main GDH */
2196                 td->mainSWGDH = mainGDH;
2197         }
2198
2199 #endif /* ANGBAND_LITE_MAC */
2200
2201         {
2202                 Rect            portRect;
2203
2204 #if TARGET_API_MAC_CARBON
2205                 GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &portRect );
2206                 global_to_local( &portRect );
2207 #else
2208                 portRect = td->w->portRect;
2209 #endif
2210                 /* Clip to the window */
2211                 ClipRect(&portRect);
2212
2213                 /* Erase the window */
2214                 EraseRect(&portRect);
2215
2216                 /* Invalidate the window */
2217 #if TARGET_API_MAC_CARBON
2218                 InvalWindowRect((WindowRef)(td->w), (const Rect *)(&portRect));
2219 #else
2220                 InvalRect(&portRect);
2221 #endif
2222
2223                 /* Display the window if needed */
2224                 if (td->mapped) ShowWindow(td->w);
2225
2226                 /* Hack -- set "mapped" flag */
2227                 t->mapped_flag = td->mapped;
2228
2229                 /* Forget color */
2230                 td->last = -1;
2231         }
2232         /* Oops */
2233 /*      if (err == noErr)
2234         {
2235                 
2236         }*/
2237 }
2238
2239
2240
2241 /*
2242  * Nuke an old Term
2243  */
2244 static void Term_nuke_mac(term *t)
2245 {
2246
2247 #pragma unused (t)
2248
2249         /* XXX */
2250 }
2251
2252
2253
2254 /*
2255  * Unused
2256  */
2257 static errr Term_user_mac(int n)
2258 {
2259
2260 #pragma unused (n)
2261
2262         /* Success */
2263         return (0);
2264 }
2265
2266
2267
2268 /*
2269  * React to changes
2270  */
2271 static errr Term_xtra_mac_react(void)
2272 {
2273         term_data *td = (term_data*)(Term->data);
2274
2275
2276         /* Reset color */
2277         td->last = -1;
2278
2279 #ifdef ANGBAND_LITE_MAC
2280
2281         /* Nothing */
2282         
2283 #else /* ANGBAND_LITE_MAC */
2284
2285         /* Handle sound */
2286         if (use_sound != arg_sound)
2287         {
2288                 /* Apply request */
2289                 use_sound = arg_sound;
2290         }
2291
2292         
2293         /* Handle transparency */
2294         if (use_newstyle_graphics != arg_newstyle_graphics)
2295         {
2296                 globe_nuke();
2297
2298                 if (globe_init() != 0)
2299                 {
2300                         plog("Cannot initialize graphics!");
2301                         arg_graphics = FALSE;
2302                         arg_newstyle_graphics = FALSE;
2303                 }
2304
2305                 /* Apply request */
2306                 use_newstyle_graphics = arg_newstyle_graphics;
2307
2308                 /* Apply and Verify */
2309                 term_data_check_size(td);
2310
2311                 /* Resize the window */
2312                 term_data_resize(td);
2313  
2314                 /* Reset visuals */
2315                 reset_visuals();
2316         }
2317         
2318         /* Handle graphics */
2319         if (use_graphics != arg_graphics)
2320         {
2321                 /* Initialize graphics */
2322
2323                 if (!use_graphics && !frameP && (globe_init() != 0))
2324                 {
2325 #ifdef JP
2326                         plog("¥°¥é¥Õ¥£¥Ã¥¯¤Î½é´ü²½¤Ï½ÐÍè¤Þ¤»¤ó¤Ç¤·¤¿.");
2327 #else
2328                         plog("Cannot initialize graphics!");
2329 #endif
2330                         arg_graphics = FALSE;
2331                 }
2332
2333                 /* Apply request */
2334                 use_graphics = arg_graphics;
2335
2336                 /* Apply and Verify */
2337                 term_data_check_size(td);
2338
2339                 /* Resize the window */
2340                 term_data_resize(td);
2341
2342                 /* Reset visuals */
2343                 reset_visuals();
2344         }
2345
2346 #endif /* ANGBAND_LITE_MAC */
2347
2348         /* Success */
2349         return (0);
2350 }
2351
2352
2353 /*
2354  * Do a "special thing"
2355  */
2356 static errr Term_xtra_mac(int n, int v)
2357 {
2358         term_data *td = (term_data*)(Term->data);
2359
2360         Rect r;
2361
2362         /* Analyze */
2363         switch (n)
2364         {
2365                 /* Make a noise */
2366                 case TERM_XTRA_NOISE:
2367                 {
2368                         /* Make a noise */
2369                         SysBeep(1);
2370
2371                         /* Success */
2372                         return (0);
2373                 }
2374
2375 #ifdef ANGBAND_LITE_MAC
2376
2377                 /* Nothing */
2378
2379 #else /* ANGBAND_LITE_MAC */
2380
2381                 /* Make a sound */
2382                 case TERM_XTRA_SOUND:
2383                 {
2384                         /* Play sound */
2385                         play_sound(v, sound_volume);
2386
2387                         /* Success */
2388                         return (0);
2389                 }
2390
2391 #endif /* ANGBAND_LITE_MAC */
2392
2393                 /* Process random events */
2394                 case TERM_XTRA_BORED:
2395                 {
2396                         /* Process an event */
2397                         (void)CheckEvents(FALSE);
2398
2399                         /* Success */
2400                         return (0);
2401                 }
2402
2403                 /* Process pending events */
2404                 case TERM_XTRA_EVENT:
2405                 {
2406                         /* Process an event */
2407                         (void)CheckEvents(v);
2408
2409                         /* Success */
2410                         return (0);
2411                 }
2412
2413                 /* Flush all pending events (if any) */
2414                 case TERM_XTRA_FLUSH:
2415                 {
2416                         /* Hack -- flush all events */
2417                         while (CheckEvents(TRUE)) /* loop */;
2418
2419                         /* Success */
2420                         return (0);
2421                 }
2422
2423                 /* Hack -- Change the "soft level" */
2424                 case TERM_XTRA_LEVEL:
2425                 {
2426                         /* Activate if requested */
2427                         if (v) activate(td->w);
2428
2429                         /* Success */
2430                         return (0);
2431                 }
2432
2433                 /* Clear the screen */
2434                 case TERM_XTRA_CLEAR:
2435                 {
2436                         Rect            portRect;
2437                         
2438 #if TARGET_API_MAC_CARBON
2439                         GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &portRect );
2440                         global_to_local( &portRect );
2441 #else
2442                         portRect = td->w->portRect;
2443 #endif
2444
2445                         /* No clipping XXX XXX XXX */
2446                         ClipRect(&portRect);
2447
2448                         /* Erase the window */
2449                         EraseRect(&portRect);
2450
2451                         /* Set the color */
2452                         term_data_color(td, TERM_WHITE);
2453
2454                         /* Frame the window in white */
2455                         MoveTo(0, 0);
2456                         LineTo(0, td->size_hgt-1);
2457                         LineTo(td->size_wid-1, td->size_hgt-1);
2458                         LineTo(td->size_wid-1, 0);
2459
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;
2465                         ClipRect(&r);
2466
2467                         /* Success */
2468                         return (0);
2469                 }
2470
2471                 /* React to changes */
2472                 case TERM_XTRA_REACT:
2473                 {
2474                         /* React to changes */
2475                         return (Term_xtra_mac_react());
2476                 }
2477
2478                 /* Delay (milliseconds) */
2479                 case TERM_XTRA_DELAY:
2480                 {
2481                         /* If needed */
2482                         if (v > 0)
2483                         {
2484 #if TARGET_API_MAC_CARBON
2485                                 EventRecord tmp;
2486                                 UInt32 ticks;
2487
2488                                 /* Convert millisecs to ticks */
2489                                 ticks = (v * 60L) / 1000;
2490
2491                                 /*
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.
2497                                  */
2498                                 WaitNextEvent((EventMask)~everyEvent, &tmp, ticks, nil);
2499 #else
2500                                 long m = TickCount() + (v * 60L) / 1000;
2501
2502                                 /* Wait for it */
2503                                 while (TickCount() < m) /* loop */;
2504 #endif
2505                         }
2506
2507                         /* Success */
2508                         return (0);
2509                 }
2510         }
2511
2512         /* Oops */
2513         return (1);
2514 }
2515
2516
2517
2518 /*
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).
2523  */
2524 static errr Term_curs_mac(int x, int y)
2525 {
2526         Rect r;
2527
2528         term_data *td = (term_data*)(Term->data);
2529
2530         /* Set the color */
2531         term_data_color(td, TERM_YELLOW);
2532
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;
2538
2539         FrameRect(&r);
2540
2541         /* Success */
2542         return (0);
2543 }
2544
2545
2546 /*
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).
2551  */
2552 static errr Term_bigcurs_mac(int x, int y)
2553 {
2554         Rect r;
2555
2556         term_data *td = (term_data*)(Term->data);
2557
2558         /* Set the color */
2559         term_data_color(td, TERM_YELLOW);
2560
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;
2566
2567         FrameRect(&r);
2568
2569         /* Success */
2570         return (0);
2571 }
2572
2573
2574 /*
2575  * Low level graphics (Assumes valid input)
2576  *
2577  * Erase "n" characters starting at (x,y)
2578  */
2579 static errr Term_wipe_mac(int x, int y, int n)
2580 {
2581         Rect r;
2582
2583         term_data *td = (term_data*)(Term->data);
2584
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;
2590         EraseRect(&r);
2591
2592         /* Success */
2593         return (0);
2594 }
2595
2596
2597 /*
2598  * Low level graphics.  Assumes valid input.
2599  *
2600  * Draw several ("n") chars, with an attr, at a given location.
2601  */
2602 static errr Term_text_mac(int x, int y, int n, byte a, const char *cp)
2603 {
2604         int xp, yp;
2605
2606         term_data *td = (term_data*)(Term->data);
2607
2608         /* Set the color */
2609         term_data_color(td, (a & 0x0F));
2610
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;
2614
2615         /* Move to the correct location */
2616         MoveTo(xp, yp);
2617
2618         /* Draw the character */
2619         if (n == 1) DrawChar(*cp);
2620
2621         /* Draw the string */
2622         else DrawText(cp, 0, n);
2623
2624         /* Success */
2625         return (0);
2626 }
2627
2628
2629 /*
2630  * Low level graphics (Assumes valid input)
2631  *
2632  * Erase "n" characters starting at (x,y)
2633  */
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)
2636 {
2637         int i;
2638         Rect r2;
2639         term_data *td = (term_data*)(Term->data);
2640         GDHandle saveGDevice;
2641         GWorldPtr saveGWorld;
2642         
2643         /* Save GWorld */
2644         GetGWorld(&saveGWorld, &saveGDevice);
2645         
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;
2650         
2651         if( n > 1 )
2652         {
2653                 /* Instantiate font */
2654                 TextFont(td->font_id);
2655                 TextSize(td->font_size);
2656                 TextFace(td->font_face);
2657                 
2658                 /* Restore colors */
2659                 BackColor(blackColor);
2660                 ForeColor(whiteColor);
2661         }
2662         else
2663         {
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;*/
2668                 
2669         }
2670                 
2671         /* Scan the input */
2672         for (i = 0; i < n; i++)
2673         {
2674                 bool done = FALSE;
2675
2676                 byte a = ap[i];
2677                 char c = cp[i];
2678
2679                 /* Second byte of bigtile */
2680                 if (use_bigtile && a == 255)
2681                 {
2682                         /* Advance */
2683                         r2.left += td->tile_wid;
2684
2685                         continue;
2686                 }
2687
2688                 /* Prepare right of rectangle now */
2689                 r2.right = r2.left + td->tile_wid;
2690
2691 #ifdef ANGBAND_LITE_MAC
2692
2693                 /* No graphics */
2694
2695 #else /* ANGBAND_LITE_MAC */
2696
2697                 /* Graphics -- if Available and Needed */
2698                 if (use_graphics && ((byte)a & 0x80) && ((byte)c & 0x80))
2699                 {
2700 #if TARGET_API_MAC_CARBON
2701                         PixMapHandle    srcBitMap = GetGWorldPixMap(frameP->framePort);
2702                         PixMapHandle    destBitMap;
2703 #else
2704                         BitMapPtr srcBitMap = (BitMapPtr)(frameP->framePix);
2705                         BitMapPtr destBitMap;
2706 #endif
2707                                 
2708                         int col, row;
2709                         Rect r1;
2710
2711                         Rect terrain_r;
2712                         bool terrain_flag = FALSE;
2713                         byte ta = tap[i];
2714                         char tc = tcp[i];
2715
2716                         if ((a != ta || c != tc) &&
2717                             ((byte)ta & 0x80) && ((byte)tc & 0x80))
2718                         {
2719                                 /* Row and Col */
2720                                 row = ((byte)ta & 0x7F);
2721                                 col = ((byte)tc & 0x7F);
2722
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;
2728
2729                                 terrain_flag = TRUE;
2730                         }
2731
2732                         /* Row and Col */
2733                         row = ((byte)a & 0x7F);
2734                         col = ((byte)c & 0x7F);
2735                         
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;
2741
2742                         /* Hardwire CopyBits */
2743                         BackColor(whiteColor);
2744                         ForeColor(blackColor);
2745
2746                         /* Draw the picture */
2747 #if TARGET_API_MAC_CARBON
2748                         destBitMap = GetPortPixMap(GetWindowPort( td->w ));
2749 #else
2750                         destBitMap = (BitMapPtr)&(td->w->portBits);
2751 #endif
2752                         if (use_bigtile) r2.right += td->tile_wid;
2753
2754                         if (terrain_flag)
2755                         {
2756                                 /*
2757                                  * Source mode const = srcCopy:
2758                                  *
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
2766                                  */
2767 #if TARGET_API_MAC_CARBON
2768                                 CopyBits( (BitMap *) *srcBitMap, (BitMap *) *destBitMap, &terrain_r, &r2, srcCopy, NULL);
2769 #else
2770                                 CopyBits( srcBitMap, destBitMap, &terrain_r, &r2, srcCopy, NULL );
2771 #endif
2772                                 /*
2773                                  * Draw transparent tile
2774                                  * BackColor is ignored and the destination is
2775                                  * left untouched
2776                                  */
2777                                 BackColor(blackColor);
2778 #if TARGET_API_MAC_CARBON
2779                                 CopyBits( (BitMap *) *srcBitMap, (BitMap *) *destBitMap, &r1, &r2, transparent, NULL);
2780 #else
2781                                 CopyBits( srcBitMap, destBitMap, &r1, &r2, transparent, NULL );
2782 #endif
2783                         }
2784                         else
2785                         {
2786 #if TARGET_API_MAC_CARBON
2787                                 CopyBits( (BitMap *) *srcBitMap, (BitMap *) *destBitMap, &r1, &r2, srcCopy, NULL);
2788 #else
2789                                 CopyBits( srcBitMap, destBitMap, &r1, &r2, srcCopy, NULL );
2790 #endif
2791                         }
2792
2793                         /* Restore colors */
2794                         BackColor(blackColor);
2795                         ForeColor(whiteColor);
2796
2797                         /* Forget color */
2798                         td->last = -1;
2799
2800                         /* Done */
2801                         done = TRUE;
2802                 }
2803
2804 #endif /* ANGBAND_LITE_MAC */
2805
2806                 /* Normal */
2807                 if (!done)
2808                 {
2809                         int xp, yp;
2810
2811                         /* Set the color */
2812                         term_data_color(td, (a & 0x0F));
2813                         
2814                         /* Starting pixel */
2815                         xp = r2.left + td->tile_o_x;
2816                         yp = r2.top + td->tile_o_y;
2817                         
2818                         /* Move to the correct location */
2819                         MoveTo(xp, yp);
2820
2821 #ifdef JP
2822                         if (iskanji(c))
2823                         {
2824                                 /* Double width rectangle */
2825                                 r2.right += td->tile_wid;
2826
2827                                 /* Erase */
2828                                 EraseRect(&r2);
2829
2830                                 /* Draw the character */
2831                                 DrawText(cp, i, 2);
2832                                 
2833                                 i++;
2834                                 
2835                                 r2.left += td->tile_wid;
2836                         }
2837                         else
2838 #endif
2839                         {
2840                                 /* Erase */
2841                                 EraseRect(&r2);
2842
2843                                 /* Draw the character */
2844                                 DrawChar(c);
2845                         }
2846                 }
2847
2848                 /* Advance */
2849                 r2.left += td->tile_wid;
2850         }
2851                 
2852         /* Success */
2853         return (0);
2854 }
2855
2856
2857 /*
2858  * Create and initialize window number "i"
2859  */
2860 static void term_data_link(int i)
2861 {
2862         term *old = Term;
2863
2864         term_data *td = &data[i];
2865
2866         /* Only once */
2867         if (td->t) return;
2868
2869         /* Require mapped */
2870         if (!td->mapped) return;
2871
2872         /* Allocate */
2873         MAKE(td->t, term);
2874
2875         /* Initialize the term */
2876         term_init(td->t, td->cols, td->rows, td->keys);
2877
2878         /* Use a "software" cursor */
2879         td->t->soft_cursor = TRUE;
2880
2881         /* Erase with "white space" */
2882         td->t->attr_blank = TERM_WHITE;
2883         td->t->char_blank = ' ';
2884
2885         /* Prepare the init/nuke hooks */
2886         td->t->init_hook = Term_init_mac;
2887         td->t->nuke_hook = Term_nuke_mac;
2888
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;
2897
2898         /* Link the local structure */
2899         td->t->data = (vptr)(td);
2900
2901         /* Activate it */
2902         Term_activate(td->t);
2903
2904         /* Global pointer */
2905         angband_term[i] = td->t;
2906
2907         /* Activate old */
2908         Term_activate(old);
2909 }
2910
2911
2912
2913 #ifdef MACH_O_CARBON
2914
2915 /*
2916  * (Carbon, Bundle)
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
2923  */
2924 static char *locate_lib(char *buf, size_t size)
2925 {
2926         CFURLRef main_url = NULL;
2927         CFStringRef main_str = NULL;
2928         char *p;
2929         char *res = NULL;
2930
2931         /* Obtain the URL of the main bundle */
2932         main_url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
2933
2934         /* Oops */
2935         if (main_url == NULL) goto ret;
2936
2937         /* Convert it to POSIX pathname */
2938         main_str = CFURLCopyFileSystemPath(main_url, kCFURLPOSIXPathStyle);
2939
2940         /* Oops */
2941         if (main_str == NULL) goto ret;
2942
2943         /* Convert it again from darn unisomething encoding to ASCII */
2944         if (CFStringGetCString(main_str, buf, size, kTextEncodingUS_ASCII) == FALSE)
2945                 goto ret;
2946
2947         /* Find the last '/' in the pathname */
2948         p = strrchr(buf, '/');
2949
2950         /* Paranoia - cannot happen */
2951         if (p == NULL) goto ret;
2952
2953         /* Remove the trailing path */
2954         *p = '\0';
2955
2956         /*
2957          * Paranoia - bounds check, with 5 being the length of "/lib/"
2958          * and 1 for terminating '\0'.
2959          */
2960         if (strlen(buf) + 5 + 1 > size) goto ret;
2961
2962         /* Append "/lib/" */
2963         strcat(buf, "/lib/");
2964
2965         /* Set result */
2966         res = buf;
2967
2968 ret:
2969
2970         /* Release objects allocated and implicitly retained by the program */
2971         if (main_str) CFRelease(main_str);
2972         if (main_url) CFRelease(main_url);
2973
2974         /* pathname of the lib folder or NULL */
2975         return (res);
2976 }
2977
2978
2979 #else /* MACH_O_CARBON */
2980
2981
2982 /*
2983  * Set the "current working directory" (also known as the "default"
2984  * volume/directory) to the location of the current application.
2985  *
2986  * Code by: Maarten Hazewinkel (mmhazewi@cs.ruu.nl)
2987  *
2988  * This function does not appear to work correctly with System 6.
2989  */
2990 static void SetupAppDir(void)
2991 {
2992         FCBPBRec fcbBlock;
2993         OSErr err = noErr;
2994         char errString[100];
2995
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);
3003         if (err != noErr)
3004         {
3005 #ifdef JP
3006                 sprintf(errString, "PBGetFCBInfo ¥¨¥é¡¼ #%d.\r ½ªÎ»¤·¤Þ¤¹.", err);
3007 #else
3008                 sprintf(errString, "Fatal PBGetFCBInfo Error #%d.\r Exiting.", err);
3009 #endif
3010                 mac_warning(errString);
3011                 ExitToShell();
3012         }
3013
3014         /* Extract the Vol and Dir */
3015         app_vol = fcbBlock.ioFCBVRefNum;
3016         app_dir = fcbBlock.ioFCBParID;
3017
3018         /* Set the current working directory to that location */
3019         err = HSetVol(NULL, app_vol, app_dir);
3020         if (err != noErr)
3021         {
3022 #ifdef JP
3023                 sprintf(errString, "HSetVol ¥¨¥é¡¼ #%d.\r ½ªÎ»¤·¤Þ¤¹.", err);
3024 #else
3025                 sprintf(errString, "Fatal HSetVol Error #%d.\r Exiting.", err);
3026 #endif
3027                 mac_warning(errString);
3028                 ExitToShell();
3029         }
3030 }
3031
3032 #endif
3033
3034
3035
3036 #if TARGET_API_MAC_CARBON
3037 /*
3038  * Using Core Foundation's Preferences services -- pelpel
3039  *
3040  * Requires OS 8.6 or greater with CarbonLib 1.1 or greater. Or OS X,
3041  * of course.
3042  *
3043  * Without this, we can support older versions of OS 8 as well
3044  * (with CarbonLib 1.0.4).
3045  *
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.
3049  */
3050
3051
3052 /*
3053  * Store "value" as the value for preferences item name
3054  * pointed by key
3055  */
3056 static void save_pref_short(const char *key, short value)
3057 {
3058         CFStringRef cf_key;
3059         CFNumberRef cf_value;
3060
3061         /* allocate and initialise the key */
3062         cf_key = CFStringCreateWithCString(NULL, key, kTextEncodingUS_ASCII);
3063
3064         /* allocate and initialise the value */
3065         cf_value = CFNumberCreate(NULL, kCFNumberShortType, &value);
3066
3067         if ((cf_key != NULL) && (cf_value != NULL))
3068         {
3069                 /* Store the key-value pair in the applications preferences */
3070                 CFPreferencesSetAppValue(
3071                         cf_key,
3072                         cf_value,
3073                         kCFPreferencesCurrentApplication);
3074         }
3075
3076         /*
3077          * Free CF data - the reverse order is a vain attempt to
3078          * minimise memory fragmentation.
3079          */
3080         if (cf_value) CFRelease(cf_value);
3081         if (cf_key) CFRelease(cf_key);
3082 }
3083
3084
3085 /*
3086  * Load preference value for key, returns TRUE if it succeeds with
3087  * vptr updated appropriately, FALSE otherwise.
3088  */
3089 static bool query_load_pref_short(const char *key, short *vptr)
3090 {
3091         CFStringRef cf_key;
3092         CFNumberRef cf_value;
3093
3094         /* allocate and initialise the key */
3095         cf_key = CFStringCreateWithCString(NULL, key, kTextEncodingUS_ASCII);
3096
3097         /* Oops */
3098         if (cf_key == NULL) return (FALSE);
3099
3100         /* Retrieve value for the key */
3101         cf_value = CFPreferencesCopyAppValue(
3102                 cf_key,
3103                 kCFPreferencesCurrentApplication);
3104
3105         /* Value not found */
3106         if (cf_value == NULL)
3107         {
3108                 CFRelease(cf_key);
3109                 return (FALSE);
3110         }
3111
3112         /* Convert the value to short */
3113         CFNumberGetValue(
3114                 cf_value,
3115                 kCFNumberShortType,
3116                 vptr);
3117
3118         /* Free CF data */
3119         CFRelease(cf_value);
3120         CFRelease(cf_key);
3121
3122         /* Success */
3123         return (TRUE);
3124 }
3125
3126
3127 /*
3128  * Update short data pointed by vptr only if preferences
3129  * value for key is located.
3130  */
3131 static void load_pref_short(const char *key, short *vptr)
3132 {
3133         short tmp;
3134
3135         if (query_load_pref_short(key, &tmp)) *vptr = tmp;
3136         return;
3137 }
3138
3139
3140 /*
3141  * Save preferences to preferences file for current host+current user+
3142  * current application.
3143  */
3144 static void cf_save_prefs()
3145 {
3146         int i;
3147
3148         /* Version stamp */
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);
3153
3154         /* Gfx settings */
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);
3159
3160 #ifndef MACH_O_CARBON
3161
3162         /* SoundMode */
3163         for( i = 0 ; i < 7 ; i++ )
3164                 save_pref_short(format("sound%d.on", i), soundmode[i]);
3165
3166 #endif /* MACH_O_CARBON */
3167         
3168         /* Windows */
3169         for (i = 0; i < MAX_TERM_DATA; i++)
3170         {
3171                 term_data *td = &data[i];
3172
3173                 save_pref_short(format("term%d.mapped", i), td->mapped);
3174
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);
3178
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);
3181
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);
3186         }
3187
3188         /*
3189          * Make sure preferences are persistent
3190          */
3191         CFPreferencesAppSynchronize(
3192                 kCFPreferencesCurrentApplication);
3193 }
3194
3195
3196 /*
3197  * Load preferences from preferences file for current host+current user+
3198  * current application.
3199  */
3200 static void cf_load_prefs()
3201 {
3202         bool ok;
3203         short pref_major, pref_minor, pref_patch, pref_extra;
3204         int i;
3205
3206         MenuHandle m;
3207
3208         /* Assume nothing is wrong, yet */
3209         ok = TRUE;
3210
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);
3216
3217         /* Any of the above failed */
3218         if (!ok)
3219         {
3220                 /* This may be the first run */
3221 #ifdef JP
3222                 mac_warning("½é´üÀßÄê¥Õ¥¡¥¤¥ë¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó¡£");
3223 #else
3224                 mac_warning("Preferences are not found.");
3225 #endif
3226
3227                 /* Ignore the rest */
3228                 return;
3229         }
3230
3231 #if 0
3232
3233         /* Check version */
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))
3238         {
3239                 /* Message */
3240                 mac_warning(
3241                         format("Ignoring %d.%d.%d.%d preferences.",
3242                                 pref_major, pref_minor, pref_patch, pref_extra));
3243
3244                 /* Ignore */
3245                 return;
3246         }
3247
3248 #endif
3249
3250         /* Gfx settings */
3251         {
3252                 short pref_tmp;
3253
3254                 /* sound */
3255                 if (query_load_pref_short("arg.arg_sound", &pref_tmp))
3256                         arg_sound = pref_tmp;
3257
3258                 /* graphics */
3259                 if (query_load_pref_short("arg.arg_graphics", &pref_tmp))
3260                         arg_graphics = pref_tmp;
3261
3262                 /*newstyle graphics*/
3263                 if (query_load_pref_short("arg.arg_newstyle_graphics", &pref_tmp))
3264                 {
3265                         use_newstyle_graphics = pref_tmp;
3266                 }
3267
3268                 if (use_newstyle_graphics == true)
3269                 {
3270                         ANGBAND_GRAF = "new";
3271                         arg_newstyle_graphics = true;
3272                         grafWidth = grafHeight = 16;
3273                         pictID = 1002;
3274                 }
3275                 else
3276                 {
3277                         ANGBAND_GRAF = "old";
3278                         arg_newstyle_graphics = false;
3279                         grafWidth = grafHeight = 8;
3280                         pictID = 1001;
3281                 }
3282
3283                 /* double-width tiles */
3284                 if (query_load_pref_short("arg.arg_bigtile", &pref_tmp))
3285                 {
3286                         use_bigtile = pref_tmp;
3287                 }
3288
3289         }
3290
3291 #ifndef MACH_O_CARBON
3292
3293         /* SoundMode */
3294         for( i = 0 ; i < 7 ; i++ )
3295         {
3296                 query_load_pref_short(format("sound%d.on", i), &soundmode[i]);
3297         }
3298
3299 #endif /* MACH_O_CARBON */
3300
3301         /* Special menu */
3302         m = GetMenuHandle(134);
3303
3304         /* Item "arg_sound" */
3305         CheckMenuItem(m, 1, arg_sound);
3306
3307         /* Item "arg_graphics" */
3308         CheckMenuItem(m, 2, arg_graphics);
3309         
3310         /* Item "arg_newstyle_graphics"*/
3311         CheckMenuItem(m, 8, arg_newstyle_graphics);
3312
3313         /* Item "arg_bigtile"*/
3314         CheckMenuItem(m, 9, arg_bigtile);
3315
3316         /* Windows */
3317         for (i = 0; i < MAX_TERM_DATA; i++)
3318         {
3319                 term_data *td = &data[i];
3320
3321                 load_pref_short(format("term%d.mapped", i), &td->mapped);
3322
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);
3326
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);
3329
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);
3334         }
3335 }
3336
3337 #else
3338 /*
3339  * Global "preference" file pointer
3340  */
3341 static FILE *fff;
3342
3343 /*
3344  * Read a "short" from the file
3345  */
3346 static int getshort(void)
3347 {
3348         int x = 0;
3349         char buf[256];
3350         if (0 == my_fgets(fff, buf, sizeof(buf))) x = atoi(buf);
3351         return (x);
3352 }
3353
3354 /*
3355  * Dump a "short" to the file
3356  */
3357 static void putshort(int x)
3358 {
3359         fprintf(fff, "%d\n", x);
3360 }
3361
3362
3363
3364 /*
3365  * Write the "preference" data to the current "file"
3366  */
3367 static void save_prefs(void)
3368 {
3369         int i;
3370
3371         term_data *td;
3372
3373
3374         /*** The current version ***/
3375
3376         putshort(FAKE_VERSION);
3377         putshort(FAKE_VER_MAJOR);
3378         putshort(FAKE_VER_MINOR);
3379         putshort(FAKE_VER_PATCH);
3380
3381         putshort(arg_sound);
3382         putshort(arg_graphics);
3383         putshort(arg_newstyle_graphics);
3384         putshort(arg_bigtile);
3385         
3386         /* SoundMode */
3387         for( i = 0 ; i < 7 ; i++ )
3388                 putshort(soundmode[i]);
3389         
3390         /* Dump */
3391         for (i = 0; i < MAX_TERM_DATA; i++)
3392         {
3393                 /* Access */
3394                 td = &data[i];
3395
3396                 putshort(td->mapped);
3397
3398                 putshort(td->font_id);
3399                 putshort(td->font_size);
3400                 putshort(td->font_face);
3401
3402                 putshort(td->tile_wid);
3403                 putshort(td->tile_hgt);
3404
3405                 putshort(td->cols);
3406                 putshort(td->rows);
3407
3408                 putshort(td->r.left);
3409                 putshort(td->r.top);
3410         }
3411 }
3412
3413
3414 /*
3415  * Load the preferences from the current "file"
3416  *
3417  * XXX XXX XXX Being able to undefine various windows is
3418  * slightly bizarre, and may cause problems.
3419  */
3420 static void load_prefs(void)
3421 {
3422         int i;
3423
3424         int old_version, old_major, old_minor, old_patch;
3425
3426         term_data *td;
3427         MenuHandle m;
3428
3429         /*** Version information ***/
3430
3431         /* Preferences version */
3432         old_version = getshort();
3433         old_major = getshort();
3434         old_minor = getshort();
3435         old_patch = getshort();
3436
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))
3442         {
3443                 /* Message */
3444                 #ifdef JP
3445                 mac_warning("¸Å¤¤½é´üÀßÄê¥Õ¥¡¥¤¥ë¤ò̵»ë¤·¤Þ¤¹.");
3446                 #else
3447                 mac_warning("Ignoring old preferences.");
3448                 #endif
3449                 /* Ignore */
3450                 return;
3451         }
3452
3453         arg_sound = getshort();
3454         arg_graphics = getshort();
3455         arg_newstyle_graphics = getshort();
3456         use_newstyle_graphics = arg_newstyle_graphics;
3457         
3458         if (use_newstyle_graphics == true)
3459         {
3460                 ANGBAND_GRAF = "new";
3461                 arg_newstyle_graphics = true;
3462                 grafWidth = grafHeight = 16;
3463                 pictID = 1002;
3464         }
3465         else
3466         {
3467                 ANGBAND_GRAF = "old";
3468                 arg_newstyle_graphics = false;
3469                 grafWidth = grafHeight = 8;
3470                 pictID = 1001;
3471         }
3472
3473         arg_bigtile = getshort();
3474         use_bigtile = arg_bigtile;
3475         
3476         /* SoundMode */
3477         for( i = 0 ; i < 7 ; i++ )
3478                 soundmode[i] = getshort();
3479         
3480         /* Special menu */
3481         m = GetMenuHandle(134);
3482
3483         /* Item "arg_sound" */
3484         CheckItem(m, 1, arg_sound);
3485
3486         /* Item "arg_graphics" */
3487         CheckItem(m, 2, arg_graphics);
3488         
3489         /* Item "arg_newstyle_graphics"*/
3490         CheckItem(m, 8, arg_newstyle_graphics);
3491
3492         /* Item "arg_bigtile"*/
3493         CheckItem(m, 9, arg_bigtile);
3494
3495         /* Windows */
3496         for (i = 0; i < MAX_TERM_DATA; i++)
3497         {
3498                 /* Access */
3499                 td = &data[i];
3500
3501                 td->mapped = getshort();
3502
3503                 td->font_id = getshort();
3504                 td->font_size = getshort();
3505                 td->font_face = getshort();
3506
3507                 td->tile_wid = getshort();
3508                 td->tile_hgt = getshort();
3509
3510                 td->cols = getshort();
3511                 td->rows = getshort();
3512
3513                 td->r.left = getshort();
3514                 td->r.top = getshort();
3515
3516                 /* Done */
3517                 if (feof(fff)) break;
3518         }
3519 }
3520 #endif /* TARGET_API_MAC_CARBON */
3521
3522
3523
3524 /*
3525  * Hack -- default data for a window
3526  */
3527 static void term_data_hack(term_data *td)
3528 {
3529         short fid;
3530
3531 #if TARGET_API_MAC_CARBON
3532 #ifdef JP
3533         /* Default to Osaka font (Japanese) */
3534         fid = FMGetFontFamilyFromName( "\pOsaka¡ÝÅùÉý" );
3535 #else
3536         /* Default to Monaco font */
3537         fid = FMGetFontFamilyFromName("\pmonaco");
3538 #endif
3539 #else
3540 #ifdef JP
3541         /* Default to ÅùÉýÌÀÄ« font (Japanese) */
3542         GetFNum( "\pÅùÉýÌÀÄ«", &fid);
3543         SetFScaleDisable( true );
3544 #else
3545         /* Default to Monaco font */
3546         GetFNum("\pmonaco", &fid);
3547 #endif
3548 #endif
3549
3550         /* Wipe it */
3551         WIPE(td, term_data);
3552
3553         /* No color */
3554         td->last = -1;
3555
3556         /* Default borders */
3557         td->size_ow1 = 2;
3558         td->size_ow2 = 2;
3559         td->size_oh2 = 2;
3560
3561         /* Start hidden */
3562         td->mapped = FALSE;
3563
3564         /* Default font */
3565         td->font_id = fid;
3566
3567         /* Default font size */
3568         td->font_size = 12;
3569
3570         /* Default font face */
3571         td->font_face = 0;
3572
3573         /* Default size */
3574         td->rows = 24;
3575         td->cols = 80;
3576
3577         /* Default position */
3578         td->r.left = 10;
3579         td->r.top = 40;
3580
3581         /* Minimal keys */
3582         td->keys = 16;
3583 }
3584
3585
3586 /*
3587  * Read the preference file, Create the windows.
3588  *
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.
3592  */
3593 static void init_windows(void)
3594 {
3595         int i, b = 0;
3596
3597         term_data *td;
3598
3599 #if !TARGET_API_MAC_CARBON
3600
3601         SysEnvRec env;
3602         short savev;
3603         long saved;
3604
3605         bool oops;
3606
3607 #endif /* !TARGET_API_MAC_CARBON */
3608
3609
3610         /*** Default values ***/
3611
3612         /* Initialize (backwards) */
3613         for (i = MAX_TERM_DATA - 1; i >= 0; i--)
3614         {
3615                 int n;
3616
3617                 cptr s;
3618
3619                 /* Obtain */
3620                 td = &data[i];
3621
3622                 /* Defaults */
3623                 term_data_hack(td);
3624
3625                 /* Obtain title */
3626                 s = angband_term_name[i];
3627
3628                 /* Get length */
3629                 n = strlen(s);
3630
3631                 /* Maximal length */
3632                 if (n > 15) n = 15;
3633
3634                 /* Copy the title */
3635                 strncpy((char*)(td->title) + 1, s, n);
3636
3637                 /* Save the length */
3638                 td->title[0] = n;
3639
3640                 /* Tile the windows */
3641                 td->r.left += (b * 30);
3642                 td->r.top += (b * 30);
3643
3644                 /* Tile */
3645                 b++;
3646         }
3647
3648
3649         /*** Load preferences ***/
3650         
3651 #if TARGET_API_MAC_CARBON
3652         cf_load_prefs();
3653 #else
3654         /* Assume failure */
3655         oops = TRUE;
3656
3657         /* Assume failure */
3658         fff = NULL;
3659
3660 #ifdef USE_SFL_CODE
3661
3662         /* Block */
3663         if (TRUE)
3664         {
3665                 OSErr   err;
3666                 short   vref;
3667                 long    dirID;
3668                 char    foo[128];
3669
3670                 /* Find the folder */
3671                 err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
3672                                  &vref, &dirID);
3673
3674                 /* Success */
3675                 if (!err)
3676                 {
3677                         /* Extract a path name */
3678                         PathNameFromDirID(dirID, vref, (StringPtr)foo);
3679
3680                         /* Convert the string */
3681                         ptocstr((StringPtr)foo);
3682
3683                         /* Append the preference file name */
3684                         strcat(foo, PREF_FILE_NAME);
3685
3686                         /* Open the preference file */
3687                         fff = fopen(foo, "r");
3688
3689                         /* Success */
3690                         oops = FALSE;
3691                 }
3692         }
3693
3694 #endif /* USE_SFL_CODE */
3695
3696         /* Oops */
3697         if (oops)
3698         {
3699                 /* Save */
3700                 HGetVol(0, &savev, &saved);
3701
3702                 /* Go to the "system" folder */
3703                 SysEnvirons(curSysEnvVers, &env);
3704                 SetVol(0, env.sysVRefNum);
3705
3706                 /* Open the file */
3707                 fff = fopen(PREF_FILE_NAME, "r");
3708
3709                 /* Restore */
3710                 HSetVol(0, savev, saved);
3711         }
3712
3713         /* Load preferences */
3714         if (fff)
3715         {
3716                 /* Load a real preference file */
3717                 load_prefs();
3718
3719                 /* Close the file */
3720                 my_fclose(fff);
3721         }
3722 #endif /* TARGET_API_MAC_CARBON */
3723
3724
3725         /*** Instantiate ***/
3726
3727         /* Main window */
3728         td = &data[0];
3729
3730         /* Many keys */
3731         td->keys = 1024;
3732
3733         /* Start visible */
3734         td->mapped = TRUE;
3735
3736         /* Link (backwards, for stacking order) */
3737         for (i = MAX_TERM_DATA - 1; i >= 0; i--)
3738         {
3739                 term_data_link(i);
3740         }
3741
3742         /* Main window */
3743         td = &data[0];
3744
3745         /* Main window */
3746         Term_activate(td->t);
3747 }
3748
3749 #ifndef MACH_O_CARBON
3750
3751 static void init_sound( void )
3752 {
3753         int err, i;
3754         CInfoPBRec pb;
3755         SignedByte              permission = fsRdPerm;
3756         pascal short    ret;
3757         
3758         Handle handle;
3759         Str255 sound;
3760
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;
3767
3768         /* Check for errors */
3769         err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3770
3771         /* Success */
3772         if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3773         {
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;
3780
3781                 /* Check for errors */
3782                 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3783                         
3784                         /* Success */
3785                 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3786                 {
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;
3793
3794                         /* Check for errors */
3795                         err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3796
3797                         /* Success */
3798                         if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3799                         {
3800                                 ret = HOpenResFile( app_vol , pb.dirInfo.ioDrDirID , "\psound.rsrc" , permission );
3801                                 if( ret != -1 ){
3802                                         ext_sound = 1;
3803                                         
3804                                         for( i = 0 ; i < 7 ; i++ )
3805                                                         soundmode[i] = false;
3806                                         
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);
3811
3812                                                 /* Obtain resource XXX XXX XXX */
3813                                                 handle = Get1NamedResource('snd ', sound);
3814                                                 if( handle == NULL || ext_sound )
3815                                                         handle = GetNamedResource('snd ', sound);
3816                                                 
3817                                                 if( handle )
3818                                                         soundmode[soundchoice[i]] = true;
3819                                                 
3820                                         }
3821                                 }
3822                         }
3823                 }
3824         }
3825 }
3826
3827 static void init_graf( void )
3828 {
3829         int err, i;
3830         CInfoPBRec pb;
3831         SignedByte              permission = fsRdPerm;
3832         pascal short    ret;
3833         
3834         Handle handle;
3835         Str255 graf;
3836
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;
3843
3844         /* Check for errors */
3845         err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3846
3847         /* Success */
3848         if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3849         {
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;
3856
3857                 /* Check for errors */
3858                 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3859                         
3860                 /* Success */
3861                 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3862                 {
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;
3869
3870                         /* Check for errors */
3871                         err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3872
3873                         /* Success */
3874                         if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3875                         {
3876                                 ret = HOpenResFile( app_vol , pb.dirInfo.ioDrDirID , "\pgraf.rsrc" , permission );
3877                                 if (ret != -1)
3878                                 {
3879                                         ext_graf = 1;
3880
3881                                         /* Obtain resource XXX XXX XXX */
3882                                         handle = Get1NamedResource('PICT', graf);
3883                                         if ( handle == NULL || ext_graf )
3884                                                 handle = GetNamedResource('PICT', "\pgraf.rsrc");
3885                                 }
3886                         }
3887                 }
3888         }
3889 }
3890
3891 #endif /* MACH_O_CARBON */
3892
3893 #ifdef CHUUKEI
3894 /*
3895
3896 */
3897 static void init_chuukei( void )
3898 {
3899         char path[1024];
3900         char tmp[1024];
3901         FILE *fp;
3902         
3903         path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "chuukei.txt");
3904
3905         fp = fopen(path, "r");
3906         if(!fp)
3907                 return;
3908         
3909         /* Read a line */
3910         if (fgets(tmp, 1024, fp)){
3911                 if(tmp[0] == '-'){
3912                         int n = strlen(tmp);
3913                         tmp[n-1] = 0;
3914                         switch(tmp[1]){
3915                         case 'p':
3916                         {
3917                                 if (!tmp[2]) break;
3918                                 chuukei_server = TRUE;
3919                                 if(connect_chuukei_server(&tmp[2])<0){
3920                                         msg_print("connect fail");
3921                                         return;
3922                                 }
3923                                 msg_print("connect");
3924                                 msg_print(NULL);
3925                                 break;
3926                         }
3927
3928                         case 'c':
3929                         {
3930                                 chuukei_client = TRUE;
3931                                 connect_chuukei_server(&tmp[2]);
3932                                 play_game(FALSE);
3933                                 quit(NULL);
3934                         }
3935                         }
3936                 }
3937                 
3938         }
3939         fclose(fp);
3940         
3941 }
3942 #endif
3943
3944 /*
3945
3946 */
3947 short InevrtCheck( DialogPtr targetDlg, short check )
3948 {
3949         Handle  checkH;
3950         short   itemType;
3951         long    result;
3952         Rect    box;
3953         
3954         GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
3955         result = (GetControlValue( (ControlHandle)checkH ) + 1 ) % 2;
3956         SetControlValue( (ControlHandle)checkH , result );
3957         return result ;
3958
3959 }
3960
3961 /*
3962
3963 */
3964 short SetCheck( DialogPtr targetDlg, short check, long result )
3965 {
3966         Handle  checkH;
3967         short   itemType;
3968
3969         Rect    box;
3970         
3971         GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
3972         SetControlValue( (ControlHandle)checkH , result );
3973         return result ;
3974
3975 }
3976
3977 /*
3978
3979 */
3980 short GetCheck( DialogPtr targetDlg, short check )
3981 {
3982         Handle  checkH;
3983         short   itemType;
3984         long    result;
3985         Rect    box;
3986         
3987         GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
3988         result = GetControlValue( (ControlHandle)checkH );
3989         return result ;
3990
3991 }
3992 void SoundConfigDLog(void)
3993 {
3994         DialogPtr dialog;
3995         short item_hit;
3996         int     i;
3997
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] );
4003         
4004         /* ShowWindow(dialog); */ 
4005         for( item_hit = 100 ; cancel < item_hit ; ){
4006                 ModalDialog(0, &item_hit);
4007                 
4008                 switch(item_hit){
4009                         case ok:
4010                                 for( i = 1 ; i < 7 ; i++ )
4011                                         soundmode[i] = GetCheck( dialog, i+2 );
4012                                 break;
4013                         case cancel:
4014                                 break;
4015                         default:
4016                                 InevrtCheck( dialog, item_hit );
4017                 }
4018         }
4019         DisposeDialog(dialog);
4020
4021 }
4022
4023
4024 /*
4025  * Exit the program
4026  */
4027 #if TARGET_API_MAC_CARBON
4028 static void save_pref_file(void)
4029 {
4030         cf_save_prefs();
4031 }
4032 #else
4033 static void save_pref_file(void)
4034 {
4035         bool oops;
4036
4037         SysEnvRec env;
4038         short savev;
4039         long saved;
4040
4041
4042         /* Assume failure */
4043         oops = TRUE;
4044
4045         /* Assume failure */
4046         fff = NULL;
4047
4048         /* Text file */
4049         _ftype = 'TEXT';
4050
4051
4052 #ifdef USE_SFL_CODE
4053
4054         /* Block */
4055         if (TRUE)
4056         {
4057                 OSErr   err;
4058                 short   vref;
4059                 long    dirID;
4060                 char    foo[128];
4061
4062                 /* Find the folder */
4063                 err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
4064                                  &vref, &dirID);
4065
4066                 /* Success */
4067                 if (!err)
4068                 {
4069                         /* Extract a path name */
4070                         PathNameFromDirID(dirID, vref, (StringPtr)foo);
4071
4072                         /* Convert the string */
4073                         ptocstr((StringPtr)foo);
4074
4075                         /* Append the preference file name */
4076                         strcat(foo, PREF_FILE_NAME);
4077
4078                         /* Open the preference file */
4079                         /* my_fopen set file type and file creator for MPW */
4080                         fff = my_fopen(foo, "w");
4081
4082                         /* Success */
4083                         oops = FALSE;
4084                 }
4085         }
4086
4087 #endif /* USE_SFL_CODE */
4088
4089         /* Oops */
4090         if (oops)
4091         {
4092                 /* Save */
4093                 HGetVol(0, &savev, &saved);
4094
4095                 /* Go to "system" folder */
4096                 SysEnvirons(curSysEnvVers, &env);
4097                 SetVol(0, env.sysVRefNum);
4098
4099                 /* Open the preference file */
4100                 /* my_fopen set file type and file creator for MPW */
4101                 fff = fopen(PREF_FILE_NAME, "w");
4102
4103                 /* Restore */
4104                 HSetVol(0, savev, saved);
4105         }
4106
4107         /* Save preferences */
4108         if (fff)
4109         {
4110                 /* Write the preferences */
4111                 save_prefs();
4112
4113                 /* Close it */
4114                 my_fclose(fff);
4115         }
4116 }
4117 #endif
4118
4119
4120
4121 #if defined(__MWERKS__)
4122
4123 /*
4124  * A simple "Yes/No" filter to parse "key press" events in dialog windows
4125  */
4126 static pascal Boolean ynfilter(DialogPtr dialog, EventRecord *event, short *ip)
4127 {
4128         /* Parse key press events */
4129         if (event->what == keyDown)
4130         {
4131                 int i = 0;
4132                 char c;
4133
4134                 /* Extract the pressed key */
4135                 c = (event->message & charCodeMask);
4136
4137                 /* Accept "no" and <return> and <enter> */
4138                 if ((c=='n') || (c=='N') || (c==13) || (c==3)) i = 1;
4139
4140                 /* Accept "yes" */
4141                 else if ((c=='y') || (c=='Y')) i = 2;
4142
4143                 /* Handle "yes" or "no" */
4144                 if (i)
4145                 {
4146                         short type;
4147                         ControlHandle control;
4148                         Rect r;
4149
4150                         /* Get the button */
4151                         GetDialogItem(dialog, i, &type, (Handle*)&control, &r);
4152
4153                         /* Blink button for 1/10 second */
4154                         HiliteControl(control, 1);
4155                         Term_xtra_mac(TERM_XTRA_DELAY, 100);
4156                         HiliteControl(control, 0);
4157
4158                         /* Result */
4159                         *ip = i;
4160                         return (1);
4161                 }
4162         }
4163
4164         /* Ignore */
4165         return (0);
4166 }
4167
4168 #endif /* __MWERKS__ */
4169
4170
4171 #if TARGET_API_MAC_CARBON
4172
4173 /*
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
4177  * is 'SAVE'.
4178  * Originally written by Peter Ammon
4179  */
4180 static bool select_savefile(bool all)
4181 {
4182         OSErr err;
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;
4191
4192 #ifdef MACH_O_CARBON
4193
4194         /* Find the save folder */
4195         err = path_to_spec(ANGBAND_DIR_SAVE, &theFolderSpec);
4196
4197 #else
4198
4199         /* Find :lib:save: folder */
4200         err = FSMakeFSSpec(app_vol, app_dir, "\p:lib:save:", &theFolderSpec);
4201
4202 #endif
4203
4204         /* Oops */
4205         if (err != noErr) quit("Unable to find the folder :lib:save:");
4206
4207         /* Get default Navigator dialog options */
4208         err = NavGetDefaultDialogOptions(&dialogOptions);
4209
4210         /* Clear preview option */
4211         dialogOptions.dialogOptionFlags &= ~kNavAllowPreviews;
4212
4213         /* Disable multiple file selection */
4214         dialogOptions.dialogOptionFlags &= ~kNavAllowMultipleFiles;
4215
4216         /* Make descriptor for default location */
4217         err = AECreateDesc(typeFSS, &theFolderSpec, sizeof(FSSpec),
4218                 &defaultLocation);
4219
4220         /* Oops */
4221         if (err != noErr) quit("Unable to allocate descriptor");
4222
4223         /* We are indifferent to signature and file types */
4224         if (all)
4225         {
4226                 myTypeList = (NavTypeListHandle)nil;
4227         }
4228
4229         /* Set up type handle */
4230         else
4231         {
4232                 err = PtrToHand(&types, (Handle *)&myTypeList, sizeof(NavTypeList));
4233
4234                 /* Oops */
4235                 if (err != noErr) quit("Error in PtrToHand. Try enlarging heap");
4236
4237         }
4238
4239         /* Call NavGetFile() with the types list */
4240         err = NavChooseFile(&defaultLocation, &reply, &dialogOptions, NULL,
4241                 NULL, NULL, myTypeList, NULL);
4242
4243         /* Free type list */
4244         if (!all) DisposeHandle((Handle)myTypeList);
4245
4246         /* Error */
4247         if (err != noErr)
4248         {
4249                 /* Nothing */
4250         }
4251
4252         /* Invalid response -- allow the user to cancel */
4253         else if (!reply.validRecord)
4254         {
4255                 /* Hack -- Fake error */
4256                 err = -1;
4257         }
4258
4259         /* Retrieve FSSpec from the reply */
4260         else
4261         {
4262                 AEKeyword theKeyword;
4263                 DescType actualType;
4264                 Size actualSize;
4265
4266                 /* Get a pointer to selected file */
4267                 (void)AEGetNthPtr(&reply.selection, 1, typeFSS, &theKeyword,
4268                         &actualType, &savedGameSpec, sizeof(FSSpec), &actualSize);
4269
4270                 /* Dispose NavReplyRecord, resources and descriptors */
4271                 (void)NavDisposeReply(&reply);
4272         }
4273
4274         /* Dispose location info */
4275         AEDisposeDesc(&defaultLocation);
4276
4277         /* Error */
4278         if (err != noErr) return (FALSE);
4279
4280 #ifdef MACH_O_CARBON
4281
4282         /* Convert FSSpec to pathname and store it in variable savefile */
4283         (void)spec_to_path(&savedGameSpec, savefile, sizeof(savefile));
4284
4285 #else
4286
4287         /* Convert FSSpec to pathname and store it in variable savefile */
4288         refnum_to_name(
4289                 savefile,
4290                 savedGameSpec.parID,
4291                 savedGameSpec.vRefNum,
4292                 (char *)savedGameSpec.name);
4293
4294 #endif
4295
4296         /* Success */
4297         return (TRUE);
4298 }
4299 #endif
4300
4301
4302 /*
4303  * Handle menu: "File" + "New"
4304  */
4305 static void do_menu_file_new(void)
4306 {
4307         /* Hack */
4308         HiliteMenu(0);
4309
4310         /* Game is in progress */
4311         game_in_progress = 1;
4312
4313         /* Flush input */
4314         flush();
4315
4316         /* Play a game */
4317         play_game(TRUE);
4318
4319         /* Hack -- quit */
4320         quit(NULL);
4321 }
4322
4323
4324 /*
4325  * Handle menu: "File" + "Open"
4326  */
4327 #if TARGET_API_MAC_CARBON
4328 static void do_menu_file_open(bool all)
4329 {
4330         /* Let the player to choose savefile */
4331         if (!select_savefile(all)) return;
4332
4333         /* Hack */
4334         HiliteMenu(0);
4335
4336         /* Game is in progress */
4337         game_in_progress = TRUE;
4338
4339         /* Flush input */
4340         flush();
4341
4342         /* Play a game */
4343         play_game(FALSE);
4344
4345         /* Hack -- quit */
4346         quit(NULL);
4347 }
4348 #else
4349 static void do_menu_file_open(bool all)
4350 {
4351         int err;
4352         short vrefnum;
4353         long drefnum;
4354         long junk;
4355         DirInfo pb;
4356         SFTypeList types;
4357         SFReply reply;
4358         Point topleft;
4359
4360
4361         /* XXX XXX XXX */
4362
4363         /* vrefnum = GetSFCurVol(); */
4364         vrefnum = -*((short*)0x214);
4365
4366         /* drefnum = GetSFCurDir(); */
4367         drefnum = *((long*)0x398);
4368
4369         /* Descend into "lib" folder */
4370         pb.ioCompletion = NULL;
4371         pb.ioNamePtr = "\plib";
4372         pb.ioVRefNum = vrefnum;
4373         pb.ioDrDirID = drefnum;
4374         pb.ioFDirIndex = 0;
4375
4376         /* Check for errors */
4377         err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
4378
4379         /* Success */
4380         if ((err == noErr) && (pb.ioFlAttrib & 0x10))
4381         {
4382                 /* Descend into "lib/save" folder */
4383                 pb.ioCompletion = NULL;
4384                 pb.ioNamePtr = "\psave";
4385                 pb.ioVRefNum = vrefnum;
4386                 pb.ioDrDirID = pb.ioDrDirID;
4387                 pb.ioFDirIndex = 0;
4388
4389                 /* Check for errors */
4390                 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
4391
4392                 /* Success */
4393                 if ((err == noErr) && (pb.ioFlAttrib & 0x10))
4394                 {
4395                         /* SetSFCurDir(pb.ioDrDirID); */
4396                         *((long*)0x398) = pb.ioDrDirID;
4397                 }
4398         }
4399
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;
4403
4404         /* Allow "all" files */
4405         if (all)
4406         {
4407                 /* Get any file */
4408                 SFGetFile(topleft, "\p", NULL, -1, types, NULL, &reply);
4409         }
4410
4411         /* Allow "save" files */
4412         else
4413         {
4414                 /* Legal types */
4415                 types[0] = 'SAVE';
4416
4417                 /* Get a file */
4418                 SFGetFile(topleft, "\p", NULL, 1, types, NULL, &reply);
4419         }
4420
4421         /* Allow cancel */
4422         if (!reply.good) return;
4423
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);
4427
4428         /* Hack */
4429         HiliteMenu(0);
4430
4431         /* Game is in progress */
4432         game_in_progress = 1;
4433
4434         /* Flush input */
4435         flush();
4436
4437         /* Play a game */
4438         play_game(FALSE);
4439
4440         /* Hack -- quit */
4441         quit(NULL);
4442 }
4443 #endif
4444
4445
4446 /*
4447  * Handle the "open_when_ready" flag
4448  */
4449 static void handle_open_when_ready(void)
4450 {
4451         /* Check the flag XXX XXX XXX make a function for this */
4452         if (open_when_ready && initialized && !game_in_progress)
4453         {
4454                 /* Forget */
4455                 open_when_ready = FALSE;
4456
4457                 /* Game is in progress */
4458                 game_in_progress = 1;
4459
4460                 /* Wait for it */
4461                 pause_line(23);
4462
4463                 /* Flush input */
4464                 flush();
4465
4466                 /* Play a game */
4467                 play_game(FALSE);
4468
4469                 /* Quit */
4470                 quit(NULL);
4471         }
4472 }
4473
4474
4475
4476 /*
4477  * Initialize the menus
4478  *
4479  * Verify menus 128, 129, 130
4480  * Create menus 131, 132, 133, 134
4481  *
4482  * The standard menus are:
4483  *
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 }
4493  */
4494 static void init_menubar(void)
4495 {
4496         int i, n;
4497
4498         Rect r;
4499
4500         WindowPtr tmpw;
4501
4502         MenuHandle m;
4503         OSErr           err;
4504         long            response;
4505
4506         /* Get the "apple" menu */
4507         m = GetMenu(128);
4508
4509         /* Insert the menu */
4510         InsertMenu(m, 0);
4511
4512         /* Add the DA's to the "apple" menu */
4513 #if TARGET_API_MAC_CARBON
4514 #else
4515         AppendResMenu   (m, 'DRVR');
4516 #endif
4517
4518         /* Get the "File" menu */
4519 #if TARGET_API_MAC_CARBON
4520         m = GetMenu(129);
4521         err = Gestalt( gestaltSystemVersion, &response );
4522         if ( (err == noErr) && (response >= 0x00000A00) )
4523         {
4524                 DeleteMenuItem( m, 7 );
4525         }
4526 #else
4527         m = GetMenu(129);
4528 #endif
4529
4530         /* Insert the menu */
4531         InsertMenu(m, 0);
4532
4533
4534         /* Get the "Edit" menu */
4535         m = GetMenu(130);
4536
4537         /* Insert the menu */
4538         InsertMenu(m, 0);
4539
4540
4541         /* Make the "Font" menu */
4542         #ifdef JP
4543         m = NewMenu(131, "\p¥Õ¥©¥ó¥È");
4544         #else
4545         m = NewMenu(131, "\pFont");
4546         #endif
4547         
4548         /* Insert the menu */
4549         InsertMenu(m, 0);
4550
4551         /* Add "bold" */
4552         AppendMenu(m, "\pBold");
4553
4554         /* Add "wide" */
4555         AppendMenu(m, "\pWide");
4556
4557         /* Add a separator */
4558         AppendMenu(m, "\p-");
4559
4560         /* Fake window */
4561         r.left = r.right = r.top = r.bottom = 0;
4562
4563         /* Make the fake window */
4564         tmpw = NewWindow(0, &r, "\p", false, documentProc, 0, 0, 0);
4565
4566         /* Activate the "fake" window */
4567 #if TARGET_API_MAC_CARBON
4568         SetPortWindowPort(tmpw);
4569 #else
4570         SetPort(tmpw);
4571 #endif
4572
4573         /* Default mode */
4574         TextMode(0);
4575
4576         /* Default size */
4577         TextSize(12);
4578
4579         /* Add the fonts to the menu */
4580         AppendResMenu(m, 'FONT');
4581
4582         /* Size of menu */
4583 #if TARGET_API_MAC_CARBON
4584         n = CountMenuItems(m);
4585 #else
4586         n = CountMItems(m);
4587 #endif
4588
4589         /* Scan the menu */
4590         for (i = n; i >= 4; i--)
4591         {
4592                 Str255 tmpName;
4593                 short fontNum;
4594
4595                 /* Acquire the font name */
4596                 GetMenuItemText(m, i, tmpName);
4597
4598                 /* Acquire the font index */
4599 #if TARGET_API_MAC_CARBON
4600                 fontNum = FMGetFontFamilyFromName( tmpName );
4601 #else
4602                 GetFNum(tmpName, &fontNum);
4603 #endif
4604
4605                 /* Apply the font index */
4606                 TextFont(fontNum);
4607
4608                 /* Remove non-mono-spaced fonts */
4609                 if ((CharWidth('i') != CharWidth('W')) || (CharWidth('W') == 0))
4610                 {
4611                         /* Delete the menu item XXX XXX XXX */
4612                         DeleteMenuItem  (m, i);
4613                 }
4614         }
4615
4616         /* Destroy the old window */
4617         DisposeWindow(tmpw);
4618
4619         /* Add a separator */
4620         AppendMenu(m, "\p-");
4621
4622         /* Add the fonts to the menu */
4623         AppendResMenu   (m, 'FONT');
4624
4625
4626         /* Make the "Size" menu */
4627         #ifdef JP
4628         m = NewMenu(132, "\p¥µ¥¤¥º");
4629         #else
4630         m = NewMenu(132, "\pSize");
4631         #endif
4632         
4633         /* Insert the menu */
4634         InsertMenu(m, 0);
4635
4636         /* Add some sizes (stagger choices) */
4637         for (i = 8; i <= 32; i += ((i / 16) + 1))
4638         {
4639                 Str15 buf;
4640                 
4641                 /* Textual size */
4642                 sprintf((char*)buf + 1, "%d", i);
4643                 buf[0] = strlen((char*)buf + 1);
4644
4645                 /* Add the item */
4646                 AppendMenu(m, buf);
4647         }
4648
4649
4650         /* Make the "Windows" menu */
4651         #ifdef JP
4652         m = NewMenu(133, "\p¥¦¥¤¥ó¥É¥¦");
4653         #else
4654         m = NewMenu(133, "\pWindows");
4655         #endif
4656         
4657         /* Insert the menu */
4658         InsertMenu(m, 0);
4659
4660         /* Default choices */
4661         for (i = 0; i < MAX_TERM_DATA; i++)
4662         {
4663                 Str15 buf;
4664                 
4665                 /* Describe the item */
4666                 sprintf((char*)buf + 1, "%.15s", angband_term_name[i]);
4667                 buf[0] = strlen((char*)buf + 1);
4668
4669                 /* Add the item */
4670                 AppendMenu(m, buf);
4671
4672                 /* Command-Key shortcuts */
4673                 if (i < 8) SetItemCmd(m, i + 1, '0' + i);
4674         }
4675
4676
4677         /* Make the "Special" menu */
4678         #ifdef JP
4679         m = NewMenu(134, "\pÆÃÊÌ");
4680         #else
4681         m = NewMenu(134, "\pSpecial");
4682         #endif
4683         
4684         /* Insert the menu */
4685         InsertMenu(m, 0);
4686
4687         /* Append the choices */
4688         #ifdef JP
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£²ÇÜÉý¥¿¥¤¥ëɽ¼¨");
4698         #else
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");
4708         #endif
4709
4710         /* Make the "TileWidth" menu */
4711         #ifdef JP
4712         m = NewMenu(135, "\p¥¿¥¤¥ëÉý");
4713         #else
4714         m = NewMenu(135, "\pTileWidth");
4715         #endif
4716
4717         /* Insert the menu */
4718         InsertMenu(m, 0);
4719
4720         /* Add some sizes */
4721         for (i = 4; i <= 32; i++)
4722         {
4723                 Str15 buf;
4724                 
4725                 /* Textual size */
4726                 sprintf((char*)buf + 1, "%d", i);
4727                 buf[0] = strlen((char*)buf + 1);
4728
4729                 /* Append item */
4730                 AppendMenu(m, buf);
4731         }
4732
4733
4734         /* Make the "TileHeight" menu */
4735         #ifdef JP
4736         m = NewMenu(136, "\p¥¿¥¤¥ë¹â");
4737         #else
4738         m = NewMenu(136, "\pTileHeight");
4739         #endif
4740
4741         /* Insert the menu */
4742         InsertMenu(m, 255);
4743
4744         /* Add some sizes */
4745         for (i = 4; i <= 32; i++)
4746         {
4747                 Str15 buf;
4748
4749                 /* Textual size */
4750                 sprintf((char*)buf + 1, "%d", i);
4751                 buf[0] = strlen((char*)buf + 1);
4752
4753                 /* Append item */
4754                 AppendMenu(m, buf);
4755         }
4756
4757
4758         /* Update the menu bar */
4759         DrawMenuBar();
4760 }
4761
4762
4763 /*
4764  * Prepare the menus
4765  */
4766 static void setup_menus(void)
4767 {
4768         int i, n;
4769
4770         short value;
4771
4772         Str255 s;
4773
4774         MenuHandle m;
4775
4776         term_data *td = NULL;
4777
4778
4779         /* Relevant "term_data" */
4780         for (i = 0; i < MAX_TERM_DATA; i++)
4781         {
4782                 /* Unused */
4783                 if (!data[i].t) continue;
4784
4785                 /* Notice the matching window */
4786                 if (data[i].w == FrontWindow()) td = &data[i];
4787         }
4788
4789
4790         /* File menu */
4791         m = GetMenuHandle(129);
4792
4793         /* Get menu size */
4794 #if TARGET_API_MAC_CARBON
4795         n = CountMenuItems(m);
4796 #else
4797         n = CountMItems(m);
4798 #endif
4799
4800         /* Reset menu */
4801         for (i = 1; i <= n; i++)
4802         {
4803                 /* Reset */
4804 #if TARGET_API_MAC_CARBON
4805                 DisableMenuItem(m, i);
4806                 CheckMenuItem(m, i, FALSE);
4807 #else
4808                 DisableItem(m, i);
4809                 CheckItem(m, i, FALSE);
4810 #endif
4811         }
4812
4813         /* Enable "new"/"open..."/"import..." */
4814         if (initialized && !game_in_progress)
4815         {
4816 #if TARGET_API_MAC_CARBON
4817                 EnableMenuItem(m, 1);
4818                 EnableMenuItem(m, 2);
4819                 EnableMenuItem(m, 3);
4820 #else
4821                 EnableItem(m, 1);
4822                 EnableItem(m, 2);
4823                 EnableItem(m, 3);
4824 #endif
4825         }
4826
4827         /* Enable "close" */
4828         if (initialized)
4829         {
4830 #if TARGET_API_MAC_CARBON
4831                 EnableMenuItem(m, 4);
4832 #else
4833                 EnableItem(m, 4);
4834 #endif
4835         }
4836
4837         /* Enable "save" */
4838         if (initialized && character_generated)
4839         {
4840 #if TARGET_API_MAC_CARBON
4841                 EnableMenuItem(m, 5);
4842 #else
4843                 EnableItem(m, 5);
4844 #endif
4845         }
4846
4847         /* Enable "quit" */
4848         if (TRUE)
4849         {
4850 #if TARGET_API_MAC_CARBON
4851                 EnableMenuItem(m, 7);
4852 #else
4853                 EnableItem(m, 7);
4854 #endif
4855         }
4856
4857
4858         /* Edit menu */
4859         m = GetMenuHandle(130);
4860
4861         /* Get menu size */
4862 #if TARGET_API_MAC_CARBON
4863         n = CountMenuItems(m);
4864 #else
4865         n = CountMItems(m);
4866 #endif
4867
4868         /* Reset menu */
4869         for (i = 1; i <= n; i++)
4870         {
4871                 /* Reset */
4872 #if TARGET_API_MAC_CARBON
4873                 DisableMenuItem(m, i);
4874                 CheckMenuItem(m, i, FALSE);
4875 #else
4876                 DisableItem(m, i);
4877                 CheckItem(m, i, FALSE);
4878 #endif
4879         }
4880
4881         /* Enable "edit" options if "needed" */
4882         if (!td)
4883         {
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);
4890 #else
4891                 EnableItem(m, 1);
4892                 EnableItem(m, 3);
4893                 EnableItem(m, 4);
4894                 EnableItem(m, 5);
4895                 EnableItem(m, 6);
4896 #endif
4897         }
4898
4899
4900         /* Font menu */
4901         m = GetMenuHandle(131);
4902
4903         /* Get menu size */
4904 #if TARGET_API_MAC_CARBON
4905         n = CountMenuItems(m);
4906 #else
4907         n = CountMItems(m);
4908 #endif
4909
4910         /* Reset menu */
4911         for (i = 1; i <= n; i++)
4912         {
4913                 /* Reset */
4914 #if TARGET_API_MAC_CARBON
4915                 DisableMenuItem(m, i);
4916                 CheckMenuItem(m, i, FALSE);
4917 #else
4918                 DisableItem(m, i);
4919                 CheckItem(m, i, FALSE);
4920 #endif
4921         }
4922
4923         /* Hack -- look cute XXX XXX */
4924         /* SetItemStyle(m, 1, bold); */
4925
4926         /* Hack -- look cute XXX XXX */
4927         /* SetItemStyle(m, 2, extend); */
4928
4929         /* Active window */
4930         if (td)
4931         {
4932 #if TARGET_API_MAC_CARBON
4933                 /* Enable "bold" */
4934                 EnableMenuItem(m, 1);
4935
4936                 /* Enable "extend" */
4937                 EnableMenuItem(m, 2);
4938
4939                 /* Check the appropriate "bold-ness" */
4940                 if (td->font_face & bold) CheckMenuItem(m, 1, TRUE);
4941
4942                 /* Check the appropriate "wide-ness" */
4943                 if (td->font_face & extend) CheckMenuItem(m, 2, TRUE);
4944
4945                 /* Analyze fonts */
4946                 for (i = 4; i <= n; i++)
4947                 {
4948                         /* Enable it */
4949                         EnableMenuItem(m, i);
4950
4951                         /* Analyze font */
4952                         GetMenuItemText(m, i, s);
4953                         GetFNum(s, &value);
4954
4955                         /* Check active font */
4956                         if (td->font_id == value) CheckMenuItem(m, i, TRUE);
4957                 }
4958 #else
4959                 /* Enable "bold" */
4960                 EnableItem(m, 1);
4961
4962                 /* Enable "extend" */
4963                 EnableItem(m, 2);
4964
4965                 /* Check the appropriate "bold-ness" */
4966                 if (td->font_face & bold) CheckItem(m, 1, TRUE);
4967
4968                 /* Check the appropriate "wide-ness" */
4969                 if (td->font_face & extend) CheckItem(m, 2, TRUE);
4970
4971                 /* Analyze fonts */
4972                 for (i = 4; i <= n; i++)
4973                 {
4974                         /* Enable it */
4975                         EnableItem(m, i);
4976
4977                         /* Analyze font */
4978                         GetMenuItemText(m, i, s);
4979                         GetFNum(s, &value);
4980
4981                         /* Check active font */
4982                         if (td->font_id == value) CheckItem(m, i, TRUE);
4983                 }
4984 #endif
4985         }
4986
4987
4988         /* Size menu */
4989         m = GetMenuHandle(132);
4990
4991         /* Get menu size */
4992 #if TARGET_API_MAC_CARBON
4993         n = CountMenuItems(m);
4994 #else
4995         n = CountMItems(m);
4996 #endif
4997
4998         /* Reset menu */
4999         for (i = 1; i <= n; i++)
5000         {
5001                 /* Reset */
5002 #if TARGET_API_MAC_CARBON
5003                 DisableMenuItem(m, i);
5004                 CheckMenuItem(m, i, FALSE);
5005 #else
5006                 DisableItem(m, i);
5007                 CheckItem(m, i, FALSE);
5008 #endif
5009         }
5010         
5011         /* Active window */
5012         if (td)
5013         {
5014                 /* Analyze sizes */
5015                 for (i = 1; i <= n; i++)
5016                 {
5017 #if TARGET_API_MAC_CARBON
5018                         /* Analyze size */
5019                         GetMenuItemText(m, i, s);
5020                         s[s[0]+1] = '\0';
5021                         value = atoi((char*)(s+1));
5022
5023                         /* Enable the "real" sizes */
5024                         if (RealFont(td->font_id, value)) EnableMenuItem(m, i);
5025
5026                         /* Check the current size */
5027                         if (td->font_size == value) CheckMenuItem(m, i, TRUE);
5028 #else
5029                         /* Analyze size */
5030                         GetMenuItemText(m, i, s);
5031                         s[s[0]+1] = '\0';
5032                         value = atoi((char*)(s+1));
5033
5034                         /* Enable the "real" sizes */
5035                         if (RealFont(td->font_id, value)) EnableItem(m, i);
5036
5037                         /* Check the current size */
5038                         if (td->font_size == value) CheckItem(m, i, TRUE);
5039 #endif
5040                 }
5041         }
5042
5043
5044         /* Windows menu */
5045         m = GetMenuHandle(133);
5046
5047         /* Get menu size */
5048 #if TARGET_API_MAC_CARBON
5049         n = CountMenuItems(m);
5050 #else
5051         n = CountMItems(m);
5052 #endif
5053
5054         /* Check active windows */
5055         for (i = 1; i <= n; i++)
5056         {
5057                 /* Check if needed */
5058 #if TARGET_API_MAC_CARBON
5059                 CheckMenuItem(m, i, data[i-1].mapped);
5060 #else
5061                 CheckItem(m, i, data[i-1].mapped);
5062 #endif
5063         }
5064
5065
5066         /* Special menu */
5067         m = GetMenuHandle(134);
5068
5069         /* Get menu size */
5070 #if TARGET_API_MAC_CARBON
5071         n = CountMenuItems(m);
5072 #else
5073         n = CountMItems(m);
5074 #endif
5075
5076         /* Reset menu */
5077         for (i = 1; i <= n; i++)
5078         {
5079                 /* Reset */
5080 #if TARGET_API_MAC_CARBON
5081                 DisableMenuItem(m, i);
5082                 CheckMenuItem(m, i, FALSE);
5083 #else
5084                 DisableItem(m, i);
5085                 CheckItem(m, i, FALSE);
5086 #endif
5087         }
5088
5089 #if TARGET_API_MAC_CARBON
5090         /* Item "arg_sound" */
5091         EnableMenuItem(m, 1);
5092         CheckMenuItem(m, 1, arg_sound);
5093
5094         /* Item "arg_graphics" */
5095         EnableMenuItem(m, 2);
5096         CheckMenuItem(m, 2, arg_graphics);
5097
5098         /* Item "arg_fiddle" */
5099         EnableMenuItem(m, 4);
5100         CheckMenuItem(m, 4, arg_fiddle);
5101
5102         /* Item "arg_wizard" */
5103         EnableMenuItem(m, 5);
5104         CheckMenuItem(m, 5, arg_wizard);
5105
5106         /* Item "SoundSetting" */
5107         EnableMenuItem(m, 7);
5108
5109         /* Item NewStyle Graphics */
5110         EnableMenuItem(m, 8);
5111         CheckMenuItem(m, 8, use_newstyle_graphics);
5112
5113         /* Item Bigtile Mode */
5114         EnableMenuItem(m, 9);
5115         CheckMenuItem(m, 9, arg_bigtile);
5116 #else
5117         /* Item "arg_sound" */
5118         EnableItem(m, 1);
5119         CheckItem(m, 1, arg_sound);
5120
5121         /* Item "arg_graphics" */
5122         EnableItem(m, 2);
5123         CheckItem(m, 2, arg_graphics);
5124
5125         /* Item "arg_fiddle" */
5126         EnableItem(m, 4);
5127         CheckItem(m, 4, arg_fiddle);
5128
5129         /* Item "arg_wizard" */
5130         EnableItem(m, 5);
5131         CheckItem(m, 5, arg_wizard);
5132
5133         /* Item "SoundSetting" */
5134         EnableItem(m, 7);
5135
5136         /* Item NewStyle Graphics */
5137         EnableItem(m, 8);
5138         CheckItem(m, 8, use_newstyle_graphics);
5139
5140         /* Item Bigtile Mode */
5141         EnableItem(m, 9);
5142         CheckItem(m, 9, arg_bigtile);
5143 #endif
5144
5145         /* TileWidth menu */
5146         m = GetMenuHandle(135);
5147
5148         /* Get menu size */
5149 #if TARGET_API_MAC_CARBON
5150         n = CountMenuItems(m);
5151 #else
5152         n = CountMItems(m);
5153 #endif
5154
5155         /* Reset menu */
5156         for (i = 1; i <= n; i++)
5157         {
5158                 /* Reset */
5159 #if TARGET_API_MAC_CARBON
5160                 DisableMenuItem(m, i);
5161                 CheckMenuItem(m, i, FALSE);
5162 #else
5163                 DisableItem(m, i);
5164                 CheckItem(m, i, FALSE);
5165 #endif
5166         }
5167
5168         /* Active window */
5169         if (td)
5170         {
5171                 /* Analyze sizes */
5172                 for (i = 1; i <= n; i++)
5173                 {
5174                         /* Analyze size */
5175                         /* GetMenuItemText(m,i,s); */
5176                         GetMenuItemText(m, i, s);
5177                         s[s[0]+1] = '\0';
5178                         value = atoi((char*)(s+1));
5179
5180 #if TARGET_API_MAC_CARBON
5181                         /* Enable */
5182                         EnableMenuItem(m, i);
5183
5184                         /* Check the current size */
5185                         if (td->tile_wid == value) CheckMenuItem(m, i, TRUE);
5186 #else
5187                         /* Enable */
5188                         EnableItem(m, i);
5189
5190                         /* Check the current size */
5191                         if (td->tile_wid == value) CheckItem(m, i, TRUE);
5192 #endif
5193                 }
5194         }
5195
5196
5197         /* TileHeight menu */
5198         m = GetMenuHandle(136);
5199
5200         /* Get menu size */
5201 #if TARGET_API_MAC_CARBON
5202         n = CountMenuItems(m);
5203 #else
5204         n = CountMItems(m);
5205 #endif
5206
5207         /* Reset menu */
5208         for (i = 1; i <= n; i++)
5209         {
5210                 /* Reset */
5211 #if TARGET_API_MAC_CARBON
5212                 DisableMenuItem(m, i);
5213                 CheckMenuItem(m, i, FALSE);
5214 #else
5215                 DisableItem(m, i);
5216                 CheckItem(m, i, FALSE);
5217 #endif
5218         }
5219
5220         /* Active window */
5221         if (td)
5222         {
5223                 /* Analyze sizes */
5224                 for (i = 1; i <= n; i++)
5225                 {
5226                         /* Analyze size */
5227                         GetMenuItemText(m, i, s);
5228                         s[s[0]+1] = '\0';
5229                         value = atoi((char*)(s+1));
5230
5231 #if TARGET_API_MAC_CARBON
5232                         /* Enable */
5233                         EnableMenuItem(m, i);
5234
5235                         /* Check the current size */
5236                         if (td->tile_hgt == value) CheckMenuItem(m, i, TRUE);
5237 #else
5238                         /* Enable */
5239                         EnableItem(m, i);
5240
5241                         /* Check the current size */
5242                         if (td->tile_hgt == value) CheckItem(m, i, TRUE);
5243 #endif
5244                 }
5245         }
5246 }
5247
5248
5249 /*
5250  * Process a menu selection (see above)
5251  *
5252  * Hack -- assume that invalid menu selections are disabled above,
5253  * which I have been informed may not be reliable.  XXX XXX XXX
5254  */
5255 static void menu(long mc)
5256 {
5257         int i;
5258
5259         int menuid, selection;
5260
5261         static unsigned char s[1000];
5262
5263         short fid;
5264
5265         term_data *td = NULL;
5266
5267         WindowPtr old_win;
5268
5269
5270         /* Analyze the menu command */
5271         menuid = HiWord(mc);
5272         selection = LoWord(mc);
5273
5274
5275         /* Find the window */
5276         for (i = 0; i < MAX_TERM_DATA; i++)
5277         {
5278                 /* Skip dead windows */
5279                 if (!data[i].t) continue;
5280
5281                 /* Notice matches */
5282                 if (data[i].w == FrontWindow()) td = &data[i];
5283         }
5284
5285
5286         /* Branch on the menu */
5287         switch (menuid)
5288         {
5289                 /* Apple Menu */
5290                 case 128:
5291                 {
5292                         /* About Angband... */
5293 #if TARGET_API_MAC_CARBON
5294                         if (selection == 1)
5295                         {
5296                                 DialogPtr dialog;
5297                                 short item_hit;
5298
5299                                 /* Get the about dialogue */
5300                                 dialog=GetNewDialog(128, 0, (WindowPtr)-1);
5301
5302                                 /* Move it to the middle of the screen */
5303                                 RepositionWindow(
5304                                         GetDialogWindow(dialog),
5305                                         NULL,
5306                                         kWindowCenterOnMainScreen);
5307
5308                                 /* Show the dialog */
5309                                 TransitionWindow(GetDialogWindow(dialog),
5310                                         kWindowZoomTransitionEffect,
5311                                         kWindowShowTransitionAction,
5312                                         NULL);
5313
5314                                 /* Wait for user to click on it */
5315                                 ModalDialog(0, &item_hit);
5316
5317                                 /* Free the dialogue */
5318                                 DisposeDialog(dialog);
5319                                 break;
5320                         }
5321 #else
5322                         if (selection == 1)
5323                         {
5324                                 DialogPtr dialog;
5325                                 Rect r;
5326                                 short item_hit;
5327
5328                                 dialog=GetNewDialog(128, 0, (WindowPtr)-1);
5329
5330                                 r=dialog->portRect;
5331                                 center_rect(&r, &qd.screenBits.bounds);
5332                                 MoveWindow(dialog, r.left, r.top, 1);
5333                                 ShowWindow(dialog);
5334                                 ModalDialog(0, &item_hit);
5335                                 DisposeDialog(dialog);
5336                                 break;
5337                         }
5338
5339                         /* Desk accessory */
5340                         /* GetMenuItemText(GetMHandle(128),selection,s); */
5341                         GetMenuItemText(GetMenuHandle(128), selection, s);
5342                         OpenDeskAcc(s);
5343                         break;
5344 #endif
5345                 }
5346
5347                 /* File Menu */
5348                 case 129:
5349                 {
5350                         switch (selection)
5351                         {
5352                                 /* New */
5353                                 case 1:
5354                                 {
5355                                         do_menu_file_new();
5356                                         break;
5357                                 }
5358
5359                                 /* Open... */
5360                                 case 2:
5361                                 {
5362                                         do_menu_file_open(FALSE);
5363                                         break;
5364                                 }
5365
5366                                 /* Import... */
5367                                 case 3:
5368                                 {
5369                                         do_menu_file_open(TRUE);
5370                                         break;
5371                                 }
5372
5373                                 /* Close */
5374                                 case 4:
5375                                 {
5376                                         /* No window */
5377                                         if (!td) break;
5378
5379                                         /* Not Mapped */
5380                                         td->mapped = FALSE;
5381
5382                                         /* Not Mapped */
5383                                         td->t->mapped_flag = FALSE;
5384
5385                                         /* Hide the window */
5386                                         HideWindow(td->w);
5387
5388                                         break;
5389                                 }
5390
5391                                 /* Save */
5392                                 case 5:
5393                                 {
5394                                         if (!can_save){
5395 #ifdef JP
5396                                                 plog("º£¤Ï¥»¡¼¥Ö¤¹¤ë¤³¤È¤Ï½ÐÍè¤Þ¤»¤ó¡£");
5397 #else
5398                                                 plog("You may not do that right now.");
5399 #endif
5400                                                 break;
5401                                         }
5402                                         
5403                                         /* Hack -- Forget messages */
5404                                         msg_flag = FALSE;
5405
5406                                         /* Hack -- Save the game */
5407                                         do_cmd_save_game(FALSE);
5408
5409                                         break;
5410                                 }
5411
5412                                 /* Quit (with save) */
5413                                 case 7:
5414                                 {
5415                                         /* Save the game (if necessary) */
5416                                         if (game_in_progress && character_generated)
5417                                         {
5418                                                 if (!can_save){
5419 #ifdef JP
5420                                                         plog("º£¤Ï¥»¡¼¥Ö¤¹¤ë¤³¤È¤Ï½ÐÍè¤Þ¤»¤ó¡£");
5421 #else
5422                                                         plog("You may not do that right now.");
5423 #endif
5424                                                         break;
5425                                                 }
5426                                                 /* Hack -- Forget messages */
5427                                                 msg_flag = FALSE;
5428
5429                                                 /* Save the game */
5430 #if 0
5431                                                 do_cmd_save_game(FALSE);
5432 #endif
5433                                                 Term_key_push(SPECIAL_KEY_QUIT);
5434                                                 break;
5435                                         }
5436
5437                                         /* Quit */
5438                                         quit(NULL);
5439                                         break;
5440                                 }
5441                         }
5442                         break;
5443                 }
5444
5445                 /* Edit menu */
5446                 case 130:
5447                 {
5448                         /* Unused */
5449                         break;
5450                 }
5451
5452                 /* Font menu */
5453                 case 131:
5454                 {
5455                         /* Require a window */
5456                         if (!td) break;
5457
5458                         /* Memorize old */
5459                         old_win = active;
5460
5461                         /* Activate */
5462                         activate(td->w);
5463
5464                         /* Toggle the "bold" setting */
5465                         if (selection == 1)
5466                         {
5467                                 /* Toggle the setting */
5468                                 if (td->font_face & bold)
5469                                 {
5470                                         td->font_face &= ~bold;
5471                                 }
5472                                 else
5473                                 {
5474                                         td->font_face |= bold;
5475                                 }
5476
5477                                 /* Tile Width Hight Init */
5478                                 td->tile_wid = td->tile_hgt = 0;
5479
5480                                 /* Apply and Verify */
5481                                 term_data_check_font(td);
5482                                 term_data_check_size(td);
5483
5484                                 /* Resize and Redraw */
5485                                 term_data_resize(td);
5486                                 term_data_redraw(td);
5487
5488                                 break;
5489                         }
5490
5491                         /* Toggle the "wide" setting */
5492                         if (selection == 2)
5493                         {
5494                                 /* Toggle the setting */
5495                                 if (td->font_face & extend)
5496                                 {
5497                                         td->font_face &= ~extend;
5498                                 }
5499                                 else
5500                                 {
5501                                         td->font_face |= extend;
5502                                 }
5503
5504                                 /* Tile Width Hight Init */
5505                                 td->tile_wid = td->tile_hgt = 0;
5506
5507                                 /* Apply and Verify */
5508                                 term_data_check_font(td);
5509                                 term_data_check_size(td);
5510
5511                                 /* Resize and Redraw */
5512                                 term_data_resize(td);
5513                                 term_data_redraw(td);
5514
5515                                 break;
5516                         }
5517
5518                         /* Get a new font name */
5519                         GetMenuItemText(GetMenuHandle(131), selection, s);
5520                         GetFNum(s, &fid);
5521
5522                         /* Save the new font id */
5523                         td->font_id = fid;
5524
5525                         /* Current size is bad for new font */
5526                         if (!RealFont(td->font_id, td->font_size))
5527                         {
5528                                 /* Find similar size */
5529                                 for (i = 1; i <= 32; i++)
5530                                 {
5531                                         /* Adjust smaller */
5532                                         if (td->font_size - i >= 8)
5533                                         {
5534                                                 if (RealFont(td->font_id, td->font_size - i))
5535                                                 {
5536                                                         td->font_size -= i;
5537                                                         break;
5538                                                 }
5539                                         }
5540
5541                                         /* Adjust larger */
5542                                         if (td->font_size + i <= 128)
5543                                         {
5544                                                 if (RealFont(td->font_id, td->font_size + i))
5545                                                 {
5546                                                         td->font_size += i;
5547                                                         break;
5548                                                 }
5549                                         }
5550                                 }
5551                         }
5552
5553                         /* Tile Width Hight Init */
5554                         td->tile_wid = td->tile_hgt = 0;
5555
5556                         /* Apply and Verify */
5557                         term_data_check_font(td);
5558                         term_data_check_size(td);
5559
5560                         /* Resize and Redraw */
5561                         term_data_resize(td);
5562                         term_data_redraw(td);
5563
5564                         /* Restore the window */
5565                         activate(old_win);
5566
5567                         break;
5568                 }
5569
5570                 /* Size menu */
5571                 case 132:
5572                 {
5573                         if (!td) break;
5574
5575                         /* Save old */
5576                         old_win = active;
5577
5578                         /* Activate */
5579                         activate(td->w);
5580
5581                         GetMenuItemText(GetMenuHandle(132), selection, s);
5582                         s[s[0]+1]=0;
5583                         td->font_size = atoi((char*)(s+1));
5584
5585                         /* Tile Width Hight Init */
5586                         td->tile_wid = td->tile_hgt = 0;
5587
5588                         /* Apply and Verify */
5589                         term_data_check_font(td);
5590                         term_data_check_size(td);
5591
5592                         /* Resize and Redraw */
5593                         term_data_resize(td);
5594                         term_data_redraw(td);
5595
5596                         /* Restore */
5597                         activate(old_win);
5598
5599                         break;
5600                 }
5601
5602                 /* Window menu */
5603                 case 133:
5604                 {
5605                         /* Parse */
5606                         i = selection - 1;
5607
5608                         /* Check legality of choice */
5609                         if ((i < 0) || (i >= MAX_TERM_DATA)) break;
5610
5611                         /* Obtain the window */
5612                         td = &data[i];
5613
5614                         /* Mapped */
5615                         td->mapped = TRUE;
5616
5617                         /* Link */      
5618                         term_data_link(i);
5619
5620                         /* Mapped (?) */
5621                         td->t->mapped_flag = TRUE;
5622
5623                         /* Show the window */
5624                         ShowWindow(td->w);
5625
5626                         /* Bring to the front */
5627                         SelectWindow(td->w);
5628
5629                         break;
5630                 }
5631
5632                 /* Special menu */
5633                 case 134:
5634                 {
5635                         switch (selection)
5636                         {
5637                                 case 1:
5638                                 {
5639                                         /* Toggle arg_sound */
5640                                         arg_sound = !arg_sound;
5641
5642                                         /* React to changes */
5643                                         Term_xtra(TERM_XTRA_REACT, 0);
5644
5645                                         break;
5646                                 }
5647
5648                                 case 2:
5649                                 {
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;
5656                                                 pictID = 1001;
5657                                         }
5658
5659                                         /* Hack -- Force redraw */
5660                                         Term_key_push(KTRL('R'));
5661
5662                                         break;
5663                                 }
5664
5665                                 case 4:
5666                                 {
5667                                         arg_fiddle = !arg_fiddle;
5668                                         break;
5669                                 }
5670
5671                                 case 5:
5672                                 {
5673                                         arg_wizard = !arg_wizard;
5674                                         break;
5675                                 }
5676
5677                                 case 7:
5678                                 {
5679                                         SoundConfigDLog();
5680                                         break;
5681                                 }
5682                                 case 8:
5683                                 {
5684                                         if (streq(ANGBAND_GRAF, "old"))
5685                                         {
5686                                                 ANGBAND_GRAF = "new";
5687                                                 arg_newstyle_graphics = true;
5688                                                 grafWidth = grafHeight = 16;
5689                                                 pictID = 1002;
5690                                         }
5691                                         else
5692                                         {
5693                                                 ANGBAND_GRAF = "old";
5694                                                 arg_newstyle_graphics = false;
5695                                                 grafWidth = grafHeight = 8;
5696                                                 pictID = 1001;
5697                                         }
5698
5699                                         /* Hack -- Force redraw */
5700                                         Term_key_push(KTRL('R'));
5701                                         break;
5702                                 }
5703
5704                                 case 9: /* bigtile mode */
5705                                 {
5706                                         term_data *td = &data[0];
5707
5708                                         if (!can_save){
5709 #ifdef JP
5710                                                 plog("º£¤ÏÊѹ¹½ÐÍè¤Þ¤»¤ó¡£");
5711 #else
5712                                                 plog("You may not do that right now.");
5713 #endif
5714                                                 break;
5715                                         }
5716
5717                                         /* Toggle "arg_bigtile" */
5718                                         arg_bigtile = !arg_bigtile;
5719
5720                                         /* Activate */
5721                                         Term_activate(td->t);
5722
5723                                         /* Resize the term */
5724                                         Term_resize(td->cols, td->rows);
5725
5726                                         break;
5727                                 }
5728
5729                         }
5730
5731                         break;
5732                 }
5733
5734                 /* TileWidth menu */
5735                 case 135:
5736                 {
5737                         if (!td) break;
5738
5739                         /* Save old */
5740                         old_win = active;
5741
5742                         /* Activate */
5743                         activate(td->w);
5744
5745                         GetMenuItemText(GetMenuHandle(135), selection, s);
5746                         s[s[0]+1]=0;
5747                         td->tile_wid = atoi((char*)(s+1));
5748
5749                         /* Apply and Verify */
5750                         term_data_check_size(td);
5751
5752                         /* Resize and Redraw */
5753                         term_data_resize(td);
5754                         term_data_redraw(td);
5755
5756                         /* Restore */
5757                         activate(old_win);
5758
5759                         break;
5760                 }
5761
5762                 /* TileHeight menu */
5763                 case 136:
5764                 {
5765                         if (!td) break;
5766
5767                         /* Save old */
5768                         old_win = active;
5769
5770                         /* Activate */
5771                         activate(td->w);
5772
5773                         GetMenuItemText(GetMenuHandle(136), selection, s);
5774                         s[s[0]+1]=0;
5775                         td->tile_hgt = atoi((char*)(s+1));
5776
5777                         /* Apply and Verify */
5778                         term_data_check_size(td);
5779
5780                         /* Resize and Redraw */
5781                         term_data_resize(td);
5782                         term_data_redraw(td);
5783
5784                         /* Restore */
5785                         activate(old_win);
5786
5787                         break;
5788                 }
5789         }
5790
5791
5792         /* Clean the menu */
5793         HiliteMenu(0);
5794 }
5795
5796
5797 #ifdef USE_SFL_CODE
5798
5799
5800 /*
5801  * Check for extra required parameters -- From "Maarten Hazewinkel"
5802  */
5803 static OSErr CheckRequiredAEParams(const AppleEvent *theAppleEvent)
5804 {
5805         OSErr   aeError;
5806         DescType        returnedType;
5807         Size    actualSize;
5808
5809         aeError = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard,
5810                                     &returnedType, NULL, 0, &actualSize);
5811
5812         if (aeError == errAEDescNotFound) return (noErr);
5813
5814         if (aeError == noErr) return (errAEParamMissed);
5815
5816         return (aeError);
5817 }
5818
5819
5820 /*
5821  * Apple Event Handler -- Open Application
5822  */
5823 static pascal OSErr AEH_Start(const AppleEvent *theAppleEvent,
5824                               AppleEvent *reply, long handlerRefCon)
5825 {
5826 #pragma unused(reply, handlerRefCon)
5827
5828         return (CheckRequiredAEParams(theAppleEvent));
5829 }
5830
5831
5832 /*
5833  * Apple Event Handler -- Quit Application
5834  */
5835 static pascal OSErr AEH_Quit(const AppleEvent *theAppleEvent,
5836                              AppleEvent *reply, long handlerRefCon)
5837 {
5838 #pragma unused(reply, handlerRefCon)
5839 #if TARGET_API_MAC_CARBON
5840
5841         /* Save the game (if necessary) */
5842         if (game_in_progress && character_generated)
5843         {
5844                         if (!can_save){
5845 #ifdef JP
5846                                 plog("º£¤Ï¥»¡¼¥Ö¤¹¤ë¤³¤È¤Ï½ÐÍè¤Þ¤»¤ó¡£");
5847 #else
5848                                 plog("You may not do that right now.");
5849 #endif
5850                                 return;
5851                         }
5852                         /* Hack -- Forget messages */
5853                         msg_flag = FALSE;
5854
5855                         /* Save the game */
5856 #if 0
5857                         do_cmd_save_game(FALSE);
5858 #endif
5859                         Term_key_push(SPECIAL_KEY_QUIT);
5860                         return;
5861                 }
5862
5863                 /* Quit */
5864                 quit(NULL);
5865 #else
5866         /* Quit later */
5867         quit_when_ready = TRUE;
5868
5869         /* Check arguments */
5870         return (CheckRequiredAEParams(theAppleEvent));
5871 #endif
5872 }
5873
5874
5875 /*
5876  * Apple Event Handler -- Print Documents
5877  */
5878 static pascal OSErr AEH_Print(const AppleEvent *theAppleEvent,
5879                               AppleEvent *reply, long handlerRefCon)
5880 {
5881 #pragma unused(theAppleEvent, reply, handlerRefCon)
5882
5883         return (errAEEventNotHandled);
5884 }
5885
5886
5887 /*
5888  * Apple Event Handler by Steve Linberg (slinberg@crocker.com).
5889  *
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.
5895  *
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")
5900  */
5901 static pascal OSErr AEH_Open(const AppleEvent *theAppleEvent,
5902                              AppleEvent* reply, long handlerRefCon)
5903 {
5904 #pragma unused(reply, handlerRefCon)
5905
5906         FSSpec          myFSS;
5907         AEDescList      docList;
5908         OSErr           err;
5909         Size            actualSize;
5910         AEKeyword       keywd;
5911         DescType        returnedType;
5912         char            foo[128];
5913         FInfo           myFileInfo;
5914
5915         /* Put the direct parameter (a descriptor list) into a docList */
5916         err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &docList);
5917         if (err) return err;
5918
5919         /*
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.
5922          */
5923
5924         err = AEGetNthPtr(&docList, 1L, typeFSS, &keywd,
5925                           &returnedType, (Ptr) &myFSS, sizeof(myFSS), &actualSize);
5926         if (err) return err;
5927
5928         /* Only needed to check savefile type below */
5929         err = FSpGetFInfo(&myFSS, &myFileInfo);
5930         if (err)
5931         {
5932                 sprintf(foo, "Arg!  FSpGetFInfo failed with code %d", err);
5933                 mac_warning (foo);
5934                 return err;
5935         }
5936
5937         /* Ignore non 'SAVE' files */
5938         if (myFileInfo.fdType != 'SAVE') return noErr;
5939
5940 #ifdef MACH_O_CARBON
5941
5942         /* Extract a file name */
5943         (void)spec_to_path(&myFSS, savefile, sizeof(savefile));
5944
5945 #else
5946
5947         /* XXX XXX XXX Extract a file name */
5948         PathNameFromDirID(myFSS.parID, myFSS.vRefNum, (StringPtr)savefile);
5949         pstrcat((StringPtr)savefile, (StringPtr)&myFSS.name);
5950
5951         /* Convert the string */
5952         ptocstr((StringPtr)savefile);
5953
5954 #endif /* MACH_O_CARBON */
5955
5956         /* Delay actual open */
5957         open_when_ready = TRUE;
5958
5959         /* Dispose */
5960         err = AEDisposeDesc(&docList);
5961
5962         /* Success */
5963         return noErr;
5964 }
5965
5966
5967 #endif
5968
5969
5970
5971 /*
5972  * Macintosh modifiers (event.modifier & ccc):
5973  *   cmdKey, optionKey, shiftKey, alphaLock, controlKey
5974  *
5975  *
5976  * Macintosh Keycodes (0-63 normal, 64-95 keypad, 96-127 extra):
5977  *
5978  * Return:36
5979  * Delete:51
5980  *
5981  * Period:65
5982  * Star:67
5983  * Plus:69
5984  * Clear:71
5985  * Slash:75
5986  * Enter:76
5987  * Minus:78
5988  * Equal:81
5989  * 0-7:82-89
5990  * 8-9:91-92
5991  *
5992  * F5: 96
5993  * F6: 97
5994  * F7: 98
5995  * F3:99
5996  * F8:100
5997  * F10:109
5998  * F11:103
5999  * F13:105
6000  * F14:107
6001  * F9:101
6002  * F12:111
6003  * F15:113
6004  * Help:114
6005  * Home:115
6006  * PgUp:116
6007  * Del:117
6008  * F4: 118
6009  * End:119
6010  * F2:120
6011  * PgDn:121
6012  * F1:122
6013  * Lt:123
6014  * Rt:124
6015  * Dn:125
6016  * Up:126
6017  */
6018
6019
6020 /*
6021  * Optimize non-blocking calls to "CheckEvents()"
6022  * Idea from "Maarten Hazewinkel <mmhazewi@cs.ruu.nl>"
6023  */
6024 #define EVENT_TICKS 6
6025
6026
6027 /*
6028  * Check for Events, return TRUE if we process any
6029  *
6030  * Hack -- Handle AppleEvents if appropriate (ignore result code).
6031  */
6032 static bool CheckEvents(bool wait)
6033 {
6034         EventRecord event;
6035
6036         WindowPtr w;
6037
6038         Rect r;
6039
6040         long newsize;
6041
6042         int ch, ck;
6043
6044         int mc, ms, mo, mx;
6045
6046         int i;
6047
6048         term_data *td = NULL;
6049
6050         huge curTicks;
6051
6052         static huge lastTicks = 0L;
6053
6054
6055         /* Access the clock */
6056         curTicks = TickCount();
6057
6058         /* Hack -- Allow efficient checking for non-pending events */
6059         if (!wait && (curTicks < lastTicks + EVENT_TICKS)) return (FALSE);
6060
6061         /* Timestamp last check */
6062         lastTicks = curTicks;
6063
6064 #if TARGET_API_MAC_CARBON
6065         WaitNextEvent( everyEvent, &event, 1L, nil );
6066 #else
6067         /* Let the "system" run */
6068         SystemTask();
6069
6070         /* Get an event (or null) */
6071         GetNextEvent(everyEvent, &event);
6072 #endif
6073
6074         /* Hack -- Nothing is ready yet */
6075         if (event.what == nullEvent) return (FALSE);
6076
6077         /* Analyze the event */
6078         switch (event.what)
6079         {
6080
6081 #if 0
6082
6083                 case activateEvt:
6084                 {
6085                         w = (WindowPtr)event.message;
6086
6087                         activate(w);
6088
6089                         break;
6090                 }
6091
6092 #endif
6093
6094                 case updateEvt:
6095                 {
6096                         /* Extract the window */
6097                         w = (WindowPtr)event.message;
6098
6099                         /* Find the window */
6100                         for (i = 0; i < MAX_TERM_DATA; i++)
6101                         {
6102                                 /* Skip dead windows */
6103                                 if (!data[i].t) continue;
6104
6105                                 /* Notice matches */
6106                                 if (data[i].w == w) td = &data[i];
6107                         }
6108
6109                         /* Hack XXX XXX XXX */
6110                         BeginUpdate(w);
6111                         EndUpdate(w);
6112
6113                         /* Redraw the window */
6114                         if (td) term_data_redraw(td);
6115
6116                         break;
6117                 }
6118
6119                 case keyDown:
6120                 case autoKey:
6121                 {
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;
6127
6128                         /* Keypress: (only "valid" if ck < 96) */
6129                         ch = (event.message & charCodeMask) & 255;
6130
6131                         /* Keycode: see table above */
6132                         ck = ((event.message & keyCodeMask) >> 8) & 255;
6133
6134                         /* Command + "normal key" -> menu action */
6135                         if (mx && (ck < 64))
6136                         {
6137                                 /* Hack -- Prepare the menus */
6138                                 setup_menus();
6139
6140                                 /* Run the Menu-Handler */
6141                                 menu(MenuKey(ch));
6142
6143                                 /* Turn off the menus */
6144                                 HiliteMenu(0);
6145
6146                                 /* Done */
6147                                 break;
6148                         }
6149
6150
6151                         /* Hide the mouse pointer */
6152                         ObscureCursor();
6153
6154                         /* Normal key -> simple keypress */
6155                         if (ck < 64)
6156                         {
6157                                 /* Enqueue the keypress */
6158                                 Term_keypress(ch);
6159                         }
6160
6161                         /* Bizarre key -> encoded keypress */
6162                         else if (ck <= 127)
6163                         {
6164                                 /* Hack -- introduce with control-underscore */
6165                                 Term_keypress(31);
6166
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');
6172
6173                                 /* Hack -- Downshift and encode the keycode */
6174                                 Term_keypress('0' + (ck - 64) / 10);
6175                                 Term_keypress('0' + (ck - 64) % 10);
6176
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');
6181                         }
6182
6183                         break;
6184                 }
6185
6186                 case mouseDown:
6187                 {
6188                         int code;
6189
6190                         /* Analyze click location */
6191                         code = FindWindow(event.where, &w);
6192
6193                         /* Find the window */
6194                         for (i = 0; i < MAX_TERM_DATA; i++)
6195                         {
6196                                 /* Skip dead windows */
6197                                 if (!data[i].t) continue;
6198
6199                                 /* Notice matches */
6200                                 if (data[i].w == w) td = &data[i];
6201                         }
6202
6203                         /* Analyze */
6204                         switch (code)
6205                         {
6206                                 case inMenuBar:
6207                                 {
6208                                         setup_menus();
6209                                         menu(MenuSelect(event.where));
6210                                         HiliteMenu(0);
6211                                         break;
6212                                 }
6213 #if !TARGET_API_MAC_CARBON
6214                                 case inSysWindow:
6215                                 {
6216                                         SystemClick(&event, w);
6217                                         break;
6218                                 }
6219 #endif
6220
6221                                 case inDrag:
6222                                 {
6223                                         Point p;
6224
6225                                         WindowPtr old_win;
6226                                         BitMap screen;
6227                                         Rect portRect;
6228 #if TARGET_API_MAC_CARBON                                               
6229                                         GetQDGlobalsScreenBits( &screen );
6230 #else
6231                                         screen = qd.screenBits;
6232 #endif  
6233                                         r = screen.bounds;
6234                                         r.top += 20; /* GetMBarHeight() XXX XXX XXX */
6235                                         InsetRect(&r, 4, 4);
6236                                         DragWindow(w, event.where, &r);
6237
6238                                         /* Oops */
6239                                         if (!td) break;
6240
6241                                         /* Save */
6242                                         old_win = active;
6243
6244                                         /* Activate */
6245                                         activate(td->w);
6246
6247                                         /* Analyze */
6248 #if TARGET_API_MAC_CARBON
6249                                         GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &portRect );
6250 #else
6251                                         portRect = td->w->portRect;
6252                                         local_to_global( &portRect );
6253 #endif
6254                                         p.h = portRect.left;
6255                                         p.v = portRect.top;
6256 #if !TARGET_API_MAC_CARBON
6257                                         LocalToGlobal(&p);
6258 #endif
6259                                         td->r.left = p.h;
6260                                         td->r.top = p.v;
6261
6262                                         /* Restore */
6263                                         activate(old_win);
6264
6265                                         /* Apply and Verify */
6266                                         term_data_check_size(td);
6267
6268                                         break;
6269                                 }
6270
6271                                 case inGoAway:
6272                                 {
6273                                         /* Oops */
6274                                         if (!td) break;
6275
6276                                         /* Track the go-away box */
6277                                         if (TrackGoAway(w, event.where))
6278                                         {
6279                                                 /* Not Mapped */
6280                                                 td->mapped = FALSE;
6281
6282                                                 /* Not Mapped */
6283                                                 td->t->mapped_flag = FALSE;
6284
6285                                                 /* Hide the window */
6286                                                 HideWindow(td->w);
6287                                         }
6288
6289                                         break;
6290                                 }
6291
6292                                 case inGrow:
6293                                 {
6294                                         s16b x, y;
6295
6296                                         term *old = Term;
6297                                         BitMap          screen;
6298         
6299 #if TARGET_API_MAC_CARBON
6300                                         GetQDGlobalsScreenBits( &screen );
6301 #else
6302                                         screen = qd.screenBits;
6303 #endif
6304                                         /* Oops */
6305                                         if (!td) break;
6306
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;
6312
6313                                         /* Grow the rectangle */
6314                                         newsize = GrowWindow(w, event.where, &r);
6315
6316                                         /* Handle abort */
6317                                         if (!newsize) break;
6318
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;
6322
6323                                         /* Extract a "close" approximation */
6324                                         td->rows = y / td->tile_hgt;
6325                                         td->cols = x / td->tile_wid;
6326
6327                                         /* Apply and Verify */
6328                                         term_data_check_size(td);
6329                                         /* Activate */
6330                                         Term_activate(td->t);
6331
6332                                         /* Hack -- Resize the term */
6333                                         Term_resize(td->cols, td->rows);
6334
6335                                         /* Resize and Redraw */
6336                                         term_data_resize(td);
6337                                         term_data_redraw(td);
6338
6339                                         /* Restore */
6340                                         Term_activate(old);
6341
6342                                         break;
6343                                 }
6344
6345                                 case inContent:
6346                                 {
6347                                         SelectWindow(w);
6348
6349                                         break;
6350                                 }
6351                         }
6352
6353                         break;
6354                 }
6355
6356                 /* Disk Event -- From "Maarten Hazewinkel" */
6357                 case diskEvt:
6358                 {
6359
6360 #if TARGET_API_MAC_CARBON
6361 #else
6362                         /* check for error when mounting the disk */
6363                         if (HiWord(event.message) != noErr)
6364                         {
6365                                 Point p =
6366                                 {120, 120};
6367
6368                                 DILoad();
6369                                 DIBadMount(p, event.message);
6370                                 DIUnload();
6371                         }
6372 #endif
6373                         break;
6374                 }
6375
6376                 /* OS Event -- From "Maarten Hazewinkel" */
6377                 case osEvt:
6378                 {
6379                         switch ((event.message >> 24) & 0x000000FF)
6380                         {
6381                                 case suspendResumeMessage:
6382
6383                                 /* Resuming: activate the front window */
6384                                 if (event.message & resumeFlag)
6385                                 {
6386 #if TARGET_API_MAC_CARBON
6387                                         Cursor  arrow;
6388                                                 
6389                                         SetPortWindowPort( FrontWindow() );
6390                                         
6391                                         GetQDGlobalsArrow( &arrow );
6392                                         SetCursor(&arrow);
6393 #else
6394                                         SetPort(FrontWindow());
6395                                         SetCursor(&qd.arrow);
6396 #endif
6397                                 }
6398
6399                                 /* Suspend: deactivate the front window */
6400                                 else
6401                                 {
6402                                         /* Nothing */
6403                                 }
6404
6405                                 break;
6406                         }
6407
6408                         break;
6409                 }
6410
6411 #ifdef USE_SFL_CODE
6412
6413                 /* From "Steve Linberg" and "Maarten Hazewinkel" */
6414                 case kHighLevelEvent:
6415                 {
6416 #if TARGET_API_MAC_CARBON
6417                         AEProcessAppleEvent(&event);
6418 #else
6419                         /* Process apple events */
6420                         if (AEProcessAppleEvent(&event) != noErr)
6421                         {
6422                                 #ifdef JP
6423                                 plog("Apple Event Handler¤Î¥¨¥é¡¼¤Ç¤¹.");
6424                                 #else
6425                                 plog("Error in Apple Event Handler!");
6426                                 #endif
6427                         }
6428
6429                         /* Handle "quit_when_ready" */
6430                         if (quit_when_ready)
6431                         {
6432                                 /* Forget */
6433                                 quit_when_ready = FALSE;
6434
6435                                 /* Do the menu key */
6436                                 menu(MenuKey('q'));
6437
6438                                 /* Turn off the menus */
6439                                 HiliteMenu(0);
6440                         }
6441
6442                         /* Handle "open_when_ready" */
6443                         handle_open_when_ready();
6444 #endif
6445
6446                         break;
6447                 }
6448
6449 #endif
6450
6451         }
6452
6453
6454         /* Something happened */
6455         return (TRUE);
6456 }
6457
6458
6459
6460
6461 /*** Some Hooks for various routines ***/
6462
6463
6464 /*
6465  * Mega-Hack -- emergency lifeboat
6466  */
6467 static vptr lifeboat = NULL;
6468
6469
6470 /*
6471  * Hook to "release" memory
6472  */
6473 static vptr hook_rnfree(vptr v, huge size)
6474 {
6475
6476 #pragma unused (size)
6477
6478 #ifdef USE_MALLOC
6479
6480         /* Alternative method */
6481         free(v);
6482
6483 #else
6484
6485         /* Dispose */
6486         DisposePtr(v);
6487
6488 #endif
6489
6490         /* Success */
6491         return (NULL);
6492 }
6493
6494 /*
6495  * Hook to "allocate" memory
6496  */
6497 static vptr hook_ralloc(huge size)
6498 {
6499
6500 #ifdef USE_MALLOC
6501
6502         /* Make a new pointer */
6503         return (malloc(size));
6504
6505 #else
6506
6507         /* Make a new pointer */
6508         return (NewPtr(size));
6509
6510 #endif
6511
6512 }
6513
6514 /*
6515  * Hook to handle "out of memory" errors
6516  */
6517 static vptr hook_rpanic(huge size)
6518 {
6519
6520 #pragma unused (size)
6521
6522         /* vptr mem = NULL; */
6523
6524         /* Free the lifeboat */
6525         if (lifeboat)
6526         {
6527                 /* Free the lifeboat */
6528                 DisposePtr(lifeboat);
6529
6530                 /* Forget the lifeboat */
6531                 lifeboat = NULL;
6532
6533                 /* Mega-Hack -- Warning */
6534                 #ifdef JP
6535                 mac_warning("¥á¥â¥ê¡¼¤¬Â­¤ê¤Þ¤»¤ó!\rº£¤¹¤°½ªÎ»¤·¤Æ²¼¤µ¤¤!");
6536                 #else
6537                 mac_warning("Running out of Memory!\rAbort this process now!");
6538                 #endif
6539
6540                 /* Mega-Hack -- Never leave this function */
6541                 while (TRUE) CheckEvents(TRUE);
6542         }
6543
6544         /* Mega-Hack -- Crash */
6545         return (NULL);
6546 }
6547
6548
6549 /*
6550  * Hook to tell the user something important
6551  */
6552 static void hook_plog(cptr str)
6553 {
6554         /* Warning message */
6555         mac_warning(str);
6556 }
6557
6558 /*
6559  * Hook to tell the user something, and then quit
6560  */
6561 static void hook_quit(cptr str)
6562 {
6563         /* Warning if needed */
6564         if (str) mac_warning(str);
6565
6566 #ifdef USE_ASYNC_SOUND
6567
6568         /* Clean up sound support */
6569         cleanup_sound();
6570
6571 #endif /* USE_ASYNC_SOUND */
6572
6573         /* Write a preference file */
6574         save_pref_file();
6575
6576         /* All done */
6577         ExitToShell();
6578 }
6579
6580 /*
6581  * Hook to tell the user something, and then crash
6582  */
6583 static void hook_core(cptr str)
6584 {
6585         /* XXX Use the debugger */
6586         /* DebugStr(str); */
6587
6588         /* Warning */
6589         if (str) mac_warning(str);
6590
6591         /* Warn, then save player */
6592         #ifdef JP
6593         mac_warning("Ã×̿Ū¤Ê¥¨¥é¡¼¤Ç¤¹.\r¶¯À©Åª¤Ë¥»¡¼¥Ö¤·¤Æ½ªÎ»¤·¤Þ¤¹.");
6594         #else
6595         mac_warning("Fatal error.\rI will now attempt to save and quit.");
6596         #endif
6597
6598         /* Attempt to save */
6599         #ifdef JP
6600         if (!save_player()) mac_warning("·Ù¹ð -- ¥»¡¼¥Ö¤Ë¼ºÇÔ¤·¤Þ¤·¤¿!");
6601         #else
6602         if (!save_player()) mac_warning("Warning -- save failed!");
6603         #endif
6604         
6605         /* Quit */
6606         quit(NULL);
6607 }
6608
6609
6610
6611 /*** Main program ***/
6612
6613
6614 /*
6615  * Init some stuff
6616  *
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...
6623  *
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...
6627  */
6628 static void init_stuff(void)
6629 {
6630         int i;
6631
6632 #if !TARGET_API_MAC_CARBON
6633         short vrefnum;
6634         long drefnum;
6635         long junk;
6636
6637         SFTypeList types;
6638         SFReply reply;
6639 #endif
6640
6641         Rect r;
6642         Point topleft;
6643
6644         char path[1024];
6645
6646         BitMap screen;
6647         Rect screenRect;
6648
6649 #if TARGET_API_MAC_CARBON
6650         OSErr err = noErr;
6651         NavDialogOptions dialogOptions;
6652         FSSpec theFolderSpec;
6653         NavReplyRecord theReply;
6654 #endif
6655         /* Fake rectangle */
6656         r.left = 0;
6657         r.top = 0;
6658         r.right = 344;
6659         r.bottom = 188;
6660
6661         /* Center it */
6662 #if TARGET_API_MAC_CARBON
6663         screenRect = GetQDGlobalsScreenBits(&screen)->bounds;
6664 #else
6665         screenRect = qd.screenBits.bounds;
6666 #endif
6667         center_rect(&r, &screenRect);
6668
6669         /* Extract corner */
6670         topleft.v = r.top;
6671         topleft.h = r.left;
6672
6673
6674         /* Default to the "lib" folder with the application */
6675 #ifdef MACH_O_CARBON
6676         if (locate_lib(path, sizeof(path)) == NULL) quit(NULL);
6677 #else
6678         refnum_to_name(path, app_dir, app_vol, (char*)("\plib:"));
6679 #endif
6680
6681
6682         /* Check until done */
6683         while (1)
6684         {
6685                 /* Prepare the paths */
6686                 init_file_paths(path);
6687
6688                 /* Build the filename */
6689 #ifdef JP
6690                 path_build(path, sizeof(path), ANGBAND_DIR_FILE, "news_j.txt");
6691 #else
6692                 path_build(path, sizeof(path), ANGBAND_DIR_FILE, "news.txt");
6693 #endif
6694
6695                 /* Attempt to open and close that file */
6696                 if (0 == fd_close(fd_open(path, O_RDONLY))) break;
6697
6698                 /* Warning */
6699 #ifdef JP
6700                 plog_fmt("'%s' ¥Õ¥¡¥¤¥ë¤ò¥ª¡¼¥×¥ó½ÐÍè¤Þ¤»¤ó.", path);
6701 #else
6702                 plog_fmt("Unable to open the '%s' file.", path);
6703 #endif
6704
6705                 /* Warning */
6706 #ifdef JP
6707                 plog("Hengband¤Î'lib'¥Õ¥©¥ë¥À¤¬Â¸ºß¤·¤Ê¤¤¤«Àµ¤·¤¯Ìµ¤¤²ÄǽÀ­¤¬¤¢¤ê¤Þ¤¹.");
6708 #else
6709                 plog("The Angband 'lib' folder is probably missing or misplaced.");
6710 #endif
6711
6712                 /* Warning */
6713 #ifdef JP
6714                 plog("Please 'open' any file in any sub-folder of the 'lib' folder.");
6715 #else
6716                 plog("Please 'open' any file in any sub-folder of the 'lib' folder.");
6717 #endif
6718                 
6719 #if TARGET_API_MAC_CARBON
6720                 /* Ask the user to choose the lib folder */
6721                 err = NavGetDefaultDialogOptions(&dialogOptions);
6722
6723                 /* Paranoia */
6724                 if (err != noErr) quit(NULL);
6725
6726                 /* Set default location option */
6727                 dialogOptions.dialogOptionFlags |= kNavSelectDefaultLocation;
6728
6729                 /* Clear preview option */
6730                 dialogOptions.dialogOptionFlags &= ~(kNavAllowPreviews);
6731
6732                 /* Forbit selection of multiple files */
6733                 dialogOptions.dialogOptionFlags &= ~(kNavAllowMultipleFiles);
6734
6735                 /* Display location */
6736                 dialogOptions.location = topleft;
6737
6738                 /* Load the message for the missing folder from the resource fork */
6739                 GetIndString(dialogOptions.message, 128, 1);
6740
6741                 /* Wait for the user to choose a folder */
6742                 err = NavChooseFolder(
6743                         nil,
6744                         &theReply,
6745                         &dialogOptions,
6746                         nil,
6747                         nil,
6748                         nil);
6749
6750                 /* Assume the player doesn't want to go on */
6751                 if ((err != noErr) || !theReply.validRecord) quit(NULL);
6752
6753                 /* Retrieve FSSpec from the reply */
6754                 {
6755                         AEKeyword theKeyword;
6756                         DescType actualType;
6757                         Size actualSize;
6758
6759                         /* Get a pointer to selected folder */
6760                         err = AEGetNthPtr(
6761                                 &(theReply.selection),
6762                                 1,
6763                                 typeFSS,
6764                                 &theKeyword,
6765                                 &actualType,
6766                                 &theFolderSpec,
6767                                 sizeof(FSSpec),
6768                                 &actualSize);
6769
6770                         /* Paranoia */
6771                         if (err != noErr) quit(NULL);
6772                 }
6773
6774                 /* Free navitagor reply */
6775                 err = NavDisposeReply(&theReply);
6776
6777                 /* Paranoia */
6778                 if (err != noErr) quit(NULL);
6779
6780                 /* Extract textual file name for given file */
6781                 refnum_to_name(
6782                         path,
6783                         theFolderSpec.parID,
6784                         theFolderSpec.vRefNum,
6785                         (char *)theFolderSpec.name);
6786 #else
6787                 /* Allow "text" files */
6788                 types[0] = 'TEXT';
6789
6790                 /* Allow "save" files */
6791                 types[1] = 'SAVE';
6792
6793                 /* Allow "data" files */
6794                 types[2] = 'DATA';
6795
6796                 /* Get any file */
6797                 SFGetFile(topleft, "\p", NULL, 3, types, NULL, &reply);
6798
6799                 /* Allow cancel */
6800                 if (!reply.good) quit(NULL);
6801
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);
6805 #endif
6806
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';
6811
6812                 /* Hack -- allow "lib" folders */
6813                 if (suffix(path, "lib:")) continue;
6814
6815                 /* Hack -- Remove the "sub-folder" */
6816                 i = i - 1;
6817                 while ((i > 1) && (path[i] != ':')) i--;
6818                 if (path[i] == ':') path[i+1] = '\0';
6819         }
6820 }
6821
6822
6823 /*
6824  * Macintosh Main loop
6825  */
6826 int main(void)
6827 {
6828         EventRecord tempEvent;
6829         int numberOfMasters = 10;
6830
6831 #if !TARGET_API_MAC_CARBON
6832         /* Increase stack space by 64K */
6833         SetApplLimit(GetApplLimit() - 131072L);//65536L);
6834
6835         /* Stretch out the heap to full size */
6836         MaxApplZone();
6837 #endif
6838
6839         /* Get more Masters */
6840         while (numberOfMasters--) MoreMasters();
6841
6842 #if !TARGET_API_MAC_CARBON
6843         /* Set up the Macintosh */
6844         InitGraf(&qd.thePort);
6845         InitFonts();
6846         InitWindows();
6847         InitMenus();
6848         /* TEInit(); */
6849         InitDialogs(NULL);
6850 #endif
6851         InitCursor();
6852
6853 #ifdef JP
6854         KeyScript(smRoman);
6855 #endif
6856
6857         /* Flush events */
6858         FlushEvents(everyEvent, 0);
6859
6860         /* Flush events some more (?) */
6861         (void)EventAvail(everyEvent, &tempEvent);
6862         (void)EventAvail(everyEvent, &tempEvent);
6863         (void)EventAvail(everyEvent, &tempEvent);
6864
6865
6866 #ifdef ANGBAND_LITE_MAC
6867
6868         /* Nothing */
6869
6870 #else /* ANGBAND_LITE_MAC */
6871
6872 # if defined(powerc) || defined(__powerc)
6873
6874         /* Assume System 7 */
6875         
6876         /* Assume Color Quickdraw */
6877
6878 # else
6879
6880 #if TARGET_API_MAC_CARBON
6881
6882         {
6883                 OSErr err;
6884                 long response;
6885
6886                 /* Check for existence of Carbon */
6887                 err = Gestalt(gestaltCarbonVersion, &response);
6888
6889                 if (err != noErr) quit("This program requires Carbon API");
6890         }
6891
6892 #else
6893         /* Block */
6894         if (TRUE)
6895         {
6896                 OSErr err;
6897                 long versionNumber;
6898
6899                 /* Check the Gestalt */
6900                 err = Gestalt(gestaltSystemVersion, &versionNumber);
6901
6902                 /* Check the version */
6903                 if ((err != noErr) || (versionNumber < 0x0700))
6904                 {
6905                         #ifdef JP
6906                         quit("¤³¤Î¥×¥í¥°¥é¥à¤Ï´Á»úTalk7.x.x°Ê¹ß¤ÇÆ°ºî¤·¤Þ¤¹.");
6907                         #else
6908                         quit("You must have System 7 to use this program.");
6909                         #endif
6910                 }
6911         }
6912
6913         /* Block */
6914         if (TRUE)
6915         {
6916                 SysEnvRec env;
6917
6918                 /* Check the environs */
6919                 if (SysEnvirons(1, &env) != noErr)
6920                 {
6921                         #ifdef JP
6922                         quit("SysEnvirons ¥³¡¼¥ë¤Ï¼ºÇÔ¤·¤Þ¤·¤¿¡ª");
6923                         #else
6924                         quit("The SysEnvirons call failed!");
6925                         #endif
6926                 }
6927
6928                 /* Check for System Seven Stuff */
6929                 if (env.systemVersion < 0x0700)
6930                 {
6931                         #ifdef JP
6932                         quit("¤³¤Î¥×¥í¥°¥é¥à¤Ï´Á»úTalk7.x.x°Ê¹ß¤ÇÆ°ºî¤·¤Þ¤¹.");
6933                         #else
6934                         quit("You must have System 7 to use this program.");
6935                         #endif
6936                 }
6937
6938                 /* Check for Color Quickdraw */
6939                 if (!env.hasColorQD)
6940                 {
6941                         #ifdef JP
6942                         quit("¤³¤Î¥×¥í¥°¥é¥à¤ÏColor Quickdraw¤¬Ìµ¤¤¤ÈÆ°ºî¤·¤Þ¤»¤ó.");
6943                         #else
6944                         quit("You must have Color Quickdraw to use this program.");
6945                         #endif
6946                 }
6947         }
6948
6949 #endif /* CARBON */
6950 #endif
6951
6952 #endif /* ANGBAND_LITE_MAC */
6953
6954         /* 
6955          * Remember Mac OS version, in case we have to cope with version-specific
6956          * problems
6957          */
6958         (void)Gestalt(gestaltSystemVersion, &mac_os_version);
6959
6960 #ifdef USE_SFL_CODE
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,
6965                               0L, FALSE);
6966
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,
6971                               0L, FALSE);
6972
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,
6977                               0L, FALSE);
6978
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,
6983                               0L, FALSE);
6984 #endif
6985
6986 #ifndef MACH_O_CARBON
6987         /* Find the current application */
6988         SetupAppDir();
6989 #endif
6990
6991         /* Mark ourself as the file creator */
6992         _fcreator = ANGBAND_CREATOR;
6993
6994         /* Default to saving a "text" file */
6995         _ftype = 'TEXT';
6996
6997
6998 #if defined(__MWERKS__)
6999
7000         /* Obtian a "Universal Procedure Pointer" */
7001 #if TARGET_API_MAC_CARBON
7002         ynfilterUPP = NewModalFilterUPP(ynfilter);
7003 #else
7004         ynfilterUPP = NewModalFilterProc(ynfilter);
7005 #endif
7006
7007 #endif
7008
7009
7010         /* Hook in some "z-virt.c" hooks */
7011         rnfree_aux = hook_rnfree;
7012         ralloc_aux = hook_ralloc;
7013         rpanic_aux = hook_rpanic;
7014
7015         /* Hooks in some "z-util.c" hooks */
7016         plog_aux = hook_plog;
7017         quit_aux = hook_quit;
7018         core_aux = hook_core;
7019
7020         BackColor(blackColor);
7021         ForeColor(whiteColor);
7022
7023         /* Show the "watch" cursor */
7024         SetCursor(*(GetCursor(watchCursor)));
7025
7026         /* Prepare the menubar */
7027         init_menubar();
7028
7029         /* Prepare the windows */
7030         init_windows();
7031
7032 #ifndef MACH_O_CARBON
7033
7034         init_sound();
7035
7036         init_graf();
7037
7038 #endif
7039         
7040         /* Hack -- process all events */
7041         while (CheckEvents(TRUE)) /* loop */;
7042
7043         /* Reset the cursor */
7044 #if TARGET_API_MAC_CARBON
7045         {
7046                 Cursor  arrow;
7047                 GetQDGlobalsArrow( &arrow );
7048                 SetCursor(&arrow);
7049         }
7050 #else
7051         SetCursor( &qd.arrow );
7052 #endif
7053
7054
7055         /* Mega-Hack -- Allocate a "lifeboat" */
7056         lifeboat = NewPtr(16384);
7057
7058         /* Note the "system" */
7059         ANGBAND_SYS = "mac";
7060
7061         /* Initialize */
7062         init_stuff();
7063
7064         /* Catch nasty signals */
7065         signals_init();
7066
7067         /* Initialize */
7068         init_angband();
7069
7070
7071         /* Hack -- process all events */
7072         while (CheckEvents(TRUE)) /* loop */;
7073
7074
7075         /* We are now initialized */
7076         initialized = TRUE;
7077
7078
7079         /* Handle "open_when_ready" */
7080         handle_open_when_ready();
7081
7082 #ifdef CHUUKEI
7083         init_chuukei();
7084 #endif
7085
7086         /* Prompt the user */
7087 #ifdef JP
7088         prt("'¥Õ¥¡¥¤¥ë'¥á¥Ë¥å¡¼¤è¤ê'¿·µ¬'¤Þ¤¿¤Ï'³«¤¯...'¤òÁªÂò¤·¤Æ¤¯¤À¤µ¤¤¡£", 23, 10);
7089 #else
7090         prt("[Choose 'New' or 'Open' from the 'File' menu]", 23, 15);
7091 #endif
7092
7093         /* Flush the prompt */
7094         Term_fresh();
7095
7096
7097         /* Hack -- Process Events Forever */
7098         while (TRUE) CheckEvents(TRUE);
7099 }
7100