OSDN Git Service

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