OSDN Git Service

自動拾いエディタでfreeした領域をアクセスしているバグを修正。
[hengband/hengband.git] / src / main-mac.c
1 /* File: main-mac.c */
2
3 /* Purpose: Simple support for MACINTOSH Angband */
4
5 /*
6  * This file should only be compiled with the "Macintosh" version
7  *
8  * This file written by "Ben Harrison (benh@phial.com)".
9  *
10  * Some code adapted from "MacAngband 2.6.1" by Keith Randall
11  *
12  * Maarten Hazewinkel (mmhazewi@cs.ruu.nl) provided some initial
13  * suggestions for the PowerMac port.
14  *
15  * Steve Linberg (slinberg@crocker.com) provided the code surrounded
16  * by "USE_SFL_CODE".
17  *
18  * The graphics code is adapted from an extremely minimal subset of
19  * the code from "Sprite World II", an amazing animation package.
20  *
21  * See "z-term.c" for info on the concept of the "generic terminal"
22  *
23  * The preference file is now a text file named "Angband preferences".
24  *
25  * Note that the "preference" file is now a simple text file called
26  * "Angband preferences", which contains the versions information, so
27  * that obsolete preference files can be ignored (this may be bad).
28  *
29  * Note that "init1.c", "init2.c", "load1.c", "load2.c", and "birth.c"
30  * should probably be "unloaded" as soon as they are no longer needed,
31  * to save space, but I do not know how to do this.
32  *
33  * Stange bug -- The first "ClipRect()" call crashes if the user closes
34  * all the windows, switches to another application, switches back, and
35  * then re-opens the main window, for example, using "command-a".
36  *
37  * By default, this file assumes that you will be using a 68020 or better
38  * machine, running System 7 and Color Quickdraw.  In fact, the game will
39  * refuse to run unless these features are available.  This allows the use
40  * of a variety of interesting features such as graphics and sound.
41  *
42  * To create a version which can be used on 68000 machines, or on machines
43  * which are not running System 7 or Color Quickdraw, simply activate the
44  * "ANGBAND_LITE_MAC" compilation flag in the proper header file.  This
45  * will disable all "modern" features used in this file, including support
46  * for multiple sub-windows, color, graphics, and sound.
47  *
48  * When compiling with the "ANGBAND_LITE_MAC" flag, the "ANGBAND_LITE"
49  * flag will be automatically defined, which will disable many of the
50  * advanced features of the game itself, reducing the total memory usage.
51  *
52  * If you are never going to use "graphics" (especially if you are not
53  * compiling support for graphics anyway) then you can delete the "pict"
54  * resource with id "1001" with no dangerous side effects.
55  */
56
57
58 /*
59  * Important Resources in the resource file:
60  *
61  *   FREF 130 = 'A271' / 'APPL' (application)
62  *   FREF 129 = 'A271' / 'SAVE' (save file)
63  *   FREF 130 = 'A271' / 'TEXT' (bone file, generic text file)
64  *   FREF 131 = 'A271' / 'DATA' (binary image file, score file)
65  *
66  *   DLOG 128 = "About Angband..."
67  *
68  *   ALRT 128 = unused (?)
69  *   ALRT 129 = "Warning..."
70  *   ALRT 130 = "Are you sure you want to quit without saving?"
71  *
72  *   DITL 128 = body for DLOG 128
73  *   DITL 129 = body for ALRT 129
74  *   DITL 130 = body for ALRT 130
75  *
76  *   ICON 128 = "warning" icon
77  *
78  *   MENU 128 = apple (about, -, ...)
79  *   MENU 129 = File (new, open, close, save, -, exit, quit)
80  *   MENU 130 = Edit (undo, -, cut, copy, paste, clear)
81  *
82  *   PICT 1001 = Graphics tile set
83  */
84
85
86 /*
87  * File name patterns:
88  *   all 'APEX' files have a filename of the form "*:apex:*" (?)
89  *   all 'BONE' files have a filename of the form "*:bone:*" (?)
90  *   all 'DATA' files have a filename of the form "*:data:*"
91  *   all 'SAVE' files have a filename of the form "*:save:*"
92  *   all 'USER' files have a filename of the form "*:user:*" (?)
93  *
94  * Perhaps we should attempt to set the "_ftype" flag inside this file,
95  * to avoid nasty file type information being spread all through the
96  * rest of the code.  (?)  This might require adding hooks into the
97  * "fd_open()" and "my_fopen()" functions in "util.c".  XXX XXX XXX
98  */
99
100
101 /*
102  * Reasons for each header file:
103  *
104  *   angband.h = Angband header file
105  *
106  *   Types.h = (included anyway)
107  *   Gestalt.h = gestalt code
108  *   QuickDraw.h = (included anyway)
109  *   OSUtils.h = (included anyway)
110  *   Files.h = file code
111  *   Fonts.h = font code
112  *   Menus.h = menu code
113  *   Dialogs.h = dialog code
114  *   Windows.h = (included anyway)
115  *   Palettes.h = palette code
116  *   StandardFile.h = file dialog box
117  *   DiskInit.h = disk initialization
118  *   ToolUtils.h = HiWord() / LoWord()
119  *   Desk.h = OpenDeskAcc()
120  *   Devices.h = OpenDeskAcc()
121  *   Events.h = event code
122  *   Resources.h = resource code
123  *   Controls.h = button code
124  *   SegLoad.h = ExitToShell(), AppFile, etc
125  *   Memory.h = SetApplLimit(), NewPtr(), etc
126  *   QDOffscreen.h = GWorld code
127  *   Sound.h = Sound code
128  *
129  * For backwards compatibility:
130  *   Use GestaltEqu.h instead of Gestalt.h
131  *   Add Desk.h to include simply includes Menus.h, Devices.h, Events.h
132  */
133
134
135 #include "angband.h"
136
137 #ifdef MACH_O_CARBON
138
139 #include <Carbon/Carbon.h>
140 #include <QuickTime/QuickTime.h>
141 #include <CoreServices/CoreServices.h>
142 #include <CoreFoundation/CoreFoundation.h>
143
144 #define TARGET_API_MAC_CARBON 1
145
146 #else /* MACH_O_CARBON */
147
148 #include <Types.h>
149 #include <Gestalt.h>
150 #include <QuickDraw.h>
151 #include <Files.h>
152 #include <Fonts.h>
153 #include <Menus.h>
154 #include <Dialogs.h>
155 #include <Windows.h>
156 #include <Palettes.h>
157 #include <StandardFile.h>
158 #include <DiskInit.h>
159 #include <ToolUtils.h>
160 #include <Devices.h>
161 #include <Events.h>
162 #include <Resources.h>
163 #include <Controls.h>
164 #include <SegLoad.h>
165 #include <Memory.h>
166 #include <QDOffscreen.h>
167 #include <Sound.h>
168 #if TARGET_API_MAC_CARBON
169 #include <Navigation.h>
170 #include <CFPreferences.h>
171 #include <CFNumber.h>
172 # ifdef MAC_MPW
173 # include <CarbonStdCLib.h>
174 # endif
175 #endif
176
177 #ifdef JP
178
179 #include <Script.h>
180
181 #endif
182
183 #endif /* MACH_O_CARBON */
184
185 /*
186  * 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", arg_bigtile);
3341
3342 #ifndef MACH_O_CARBON
3343         /* SoundMode */
3344         for( i = 0 ; i < 7 ; i++ )
3345                 save_pref_short(format("sound%d.on", i), soundmode[i]);
3346 #endif /* MACH_O_CARBON */
3347
3348         /* Windows */
3349         for (i = 0; i < MAX_TERM_DATA; i++)
3350         {
3351                 term_data *td = &data[i];
3352
3353                 save_pref_short(format("term%d.mapped", i), td->mapped);
3354
3355                 save_pref_short(format("term%d.font_id", i), td->font_id);
3356                 save_pref_short(format("term%d.font_size", i), td->font_size);
3357                 save_pref_short(format("term%d.font_face", i), td->font_face);
3358
3359                 save_pref_short(format("term%d.tile_wid", i), td->tile_wid);
3360                 save_pref_short(format("term%d.tile_hgt", i), td->tile_hgt);
3361
3362                 save_pref_short(format("term%d.cols", i), td->cols);
3363                 save_pref_short(format("term%d.rows", i), td->rows);
3364                 save_pref_short(format("term%d.left", i), td->r.left);
3365                 save_pref_short(format("term%d.top", i), td->r.top);
3366         }
3367
3368         /*
3369          * Make sure preferences are persistent
3370          */
3371         CFPreferencesAppSynchronize(
3372                 kCFPreferencesCurrentApplication);
3373 }
3374
3375
3376 /*
3377  * Load preferences from preferences file for current host+current user+
3378  * current application.
3379  */
3380 static void cf_load_prefs()
3381 {
3382         bool ok;
3383         short pref_major, pref_minor, pref_patch, pref_extra;
3384         int i;
3385
3386         /* Assume nothing is wrong, yet */
3387         ok = TRUE;
3388
3389         /* Load version information */
3390         ok &= query_load_pref_short("version.major", &pref_major);
3391         ok &= query_load_pref_short("version.minor", &pref_minor);
3392         ok &= query_load_pref_short("version.patch", &pref_patch);
3393         ok &= query_load_pref_short("version.extra", &pref_extra);
3394
3395         /* Any of the above failed */
3396         if (!ok)
3397         {
3398                 /* This may be the first run */
3399 #ifdef JP
3400                 mac_warning("½é´üÀßÄê¥Õ¥¡¥¤¥ë¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó¡£");
3401 #else
3402                 mac_warning("Preferences are not found.");
3403 #endif
3404
3405                 /* Ignore the rest */
3406                 return;
3407         }
3408
3409         /* Gfx settings */
3410         {
3411                 short pref_tmp;
3412
3413                 /* sound */
3414                 if (query_load_pref_short("arg.arg_sound", &pref_tmp))
3415                         arg_sound = pref_tmp;
3416
3417                 /* graphics */
3418                 if (query_load_pref_short("arg.graf_mode", &pref_tmp))
3419                         graf_mode_req = pref_tmp;
3420
3421                 /* double-width tiles */
3422                 if (query_load_pref_short("arg.arg_bigtile", &pref_tmp))
3423                 {
3424                         arg_bigtile = use_bigtile = pref_tmp;
3425                 }
3426
3427         }
3428
3429 #ifndef MACH_O_CARBON
3430         /* SoundMode */
3431         for( i = 0 ; i < 7 ; i++ )
3432         {
3433                 query_load_pref_short(format("sound%d.on", i), &soundmode[i]);
3434         }
3435 #endif /* MACH_O_CARBON */
3436
3437         /* Windows */
3438         for (i = 0; i < MAX_TERM_DATA; i++)
3439         {
3440                 term_data *td = &data[i];
3441
3442                 load_pref_short(format("term%d.mapped", i), &td->mapped);
3443
3444                 load_pref_short(format("term%d.font_id", i), &td->font_id);
3445                 load_pref_short(format("term%d.font_size", i), &td->font_size);
3446                 load_pref_short(format("term%d.font_face", i), &td->font_face);
3447
3448                 load_pref_short(format("term%d.tile_wid", i), &td->tile_wid);
3449                 load_pref_short(format("term%d.tile_hgt", i), &td->tile_hgt);
3450
3451                 load_pref_short(format("term%d.cols", i), &td->cols);
3452                 load_pref_short(format("term%d.rows", i), &td->rows);
3453                 load_pref_short(format("term%d.left", i), &td->r.left);
3454                 load_pref_short(format("term%d.top", i), &td->r.top);
3455         }
3456 }
3457
3458 #else
3459 /*
3460  * Global "preference" file pointer
3461  */
3462 static FILE *fff;
3463
3464 /*
3465  * Read a "short" from the file
3466  */
3467 static int getshort(void)
3468 {
3469         int x = 0;
3470         char buf[256];
3471         if (0 == my_fgets(fff, buf, sizeof(buf))) x = atoi(buf);
3472         return (x);
3473 }
3474
3475 /*
3476  * Dump a "short" to the file
3477  */
3478 static void putshort(int x)
3479 {
3480         fprintf(fff, "%d\n", x);
3481 }
3482
3483
3484
3485 /*
3486  * Write the "preference" data to the current "file"
3487  */
3488 static void save_prefs(void)
3489 {
3490         int i;
3491
3492         term_data *td;
3493
3494
3495         /*** The current version ***/
3496
3497         putshort(FAKE_VERSION);
3498         putshort(FAKE_VER_MAJOR);
3499         putshort(FAKE_VER_MINOR);
3500         putshort(FAKE_VER_PATCH);
3501
3502         putshort(arg_sound);
3503         putshort(graf_mode);
3504         putshort(arg_bigtile);
3505         
3506         /* SoundMode */
3507         for( i = 0 ; i < 7 ; i++ )
3508                 putshort(soundmode[i]);
3509         
3510         /* Dump */
3511         for (i = 0; i < MAX_TERM_DATA; i++)
3512         {
3513                 /* Access */
3514                 td = &data[i];
3515
3516                 putshort(td->mapped);
3517
3518                 putshort(td->font_id);
3519                 putshort(td->font_size);
3520                 putshort(td->font_face);
3521
3522                 putshort(td->tile_wid);
3523                 putshort(td->tile_hgt);
3524
3525                 putshort(td->cols);
3526                 putshort(td->rows);
3527
3528                 putshort(td->r.left);
3529                 putshort(td->r.top);
3530         }
3531 }
3532
3533
3534 /*
3535  * Load the preferences from the current "file"
3536  *
3537  * XXX XXX XXX Being able to undefine various windows is
3538  * slightly bizarre, and may cause problems.
3539  */
3540 static void load_prefs(void)
3541 {
3542         int i;
3543
3544         int old_version, old_major, old_minor, old_patch;
3545
3546         term_data *td;
3547         MenuHandle m;
3548
3549         /*** Version information ***/
3550
3551         /* Preferences version */
3552         old_version = getshort();
3553         old_major = getshort();
3554         old_minor = getshort();
3555         old_patch = getshort();
3556
3557         /* Hack -- Verify or ignore */
3558         if ((old_version != FAKE_VERSION) ||
3559             (old_major != FAKE_VER_MAJOR) ||
3560             (old_minor != FAKE_VER_MINOR) ||
3561             (old_patch != FAKE_VER_PATCH))
3562         {
3563                 /* Message */
3564                 #ifdef JP
3565                 mac_warning("¸Å¤¤½é´üÀßÄê¥Õ¥¡¥¤¥ë¤ò̵»ë¤·¤Þ¤¹.");
3566                 #else
3567                 mac_warning("Ignoring old preferences.");
3568                 #endif
3569                 /* Ignore */
3570                 return;
3571         }
3572
3573         arg_sound = getshort();
3574         graf_mode_req = getshort();
3575         arg_bigtile = getshort();
3576         use_bigtile = arg_bigtile;
3577         
3578         /* SoundMode */
3579         for( i = 0 ; i < 7 ; i++ )
3580                 soundmode[i] = getshort();
3581         
3582         /* Windows */
3583         for (i = 0; i < MAX_TERM_DATA; i++)
3584         {
3585                 /* Access */
3586                 td = &data[i];
3587
3588                 td->mapped = getshort();
3589
3590                 td->font_id = getshort();
3591                 td->font_size = getshort();
3592                 td->font_face = getshort();
3593
3594                 td->tile_wid = getshort();
3595                 td->tile_hgt = getshort();
3596
3597                 td->cols = getshort();
3598                 td->rows = getshort();
3599
3600                 td->r.left = getshort();
3601                 td->r.top = getshort();
3602
3603                 /* Done */
3604                 if (feof(fff)) break;
3605         }
3606 }
3607 #endif /* TARGET_API_MAC_CARBON */
3608
3609
3610
3611 /*
3612  * Hack -- default data for a window
3613  */
3614 static void term_data_hack(term_data *td)
3615 {
3616         short fid;
3617
3618 #if TARGET_API_MAC_CARBON
3619 #ifdef JP
3620         /* Default to Osaka font (Japanese) */
3621         fid = FMGetFontFamilyFromName( "\pOsaka¡ÝÅùÉý" );
3622 #else
3623         /* Default to Monaco font */
3624         fid = FMGetFontFamilyFromName("\pmonaco");
3625 #endif
3626 #else
3627 #ifdef JP
3628         /* Default to ÅùÉýÌÀÄ« font (Japanese) */
3629         GetFNum( "\pÅùÉýÌÀÄ«", &fid);
3630         SetFScaleDisable( true );
3631 #else
3632         /* Default to Monaco font */
3633         GetFNum("\pmonaco", &fid);
3634 #endif
3635 #endif
3636
3637         /* Wipe it */
3638         WIPE(td, term_data);
3639
3640         /* No color */
3641         td->last = -1;
3642
3643         /* Default borders */
3644         td->size_ow1 = 2;
3645         td->size_ow2 = 2;
3646         td->size_oh2 = 2;
3647
3648         /* Start hidden */
3649         td->mapped = FALSE;
3650
3651         /* Default font */
3652         td->font_id = fid;
3653
3654         /* Default font size */
3655         td->font_size = 12;
3656
3657         /* Default font face */
3658         td->font_face = 0;
3659
3660         /* Default size */
3661         td->rows = 24;
3662         td->cols = 80;
3663
3664         /* Default position */
3665         td->r.left = 10;
3666         td->r.top = 40;
3667
3668         /* Minimal keys */
3669         td->keys = 16;
3670 }
3671
3672
3673 /*
3674  * Read the preference file, Create the windows.
3675  *
3676  * We attempt to use "FindFolder()" to track down the preference file,
3677  * but if this fails, for any reason, we will try the "SysEnvirons()"
3678  * method, which may work better with System 6.
3679  */
3680 static void init_windows(void)
3681 {
3682         int i, b = 0;
3683
3684         term_data *td;
3685
3686 #if !TARGET_API_MAC_CARBON
3687
3688         SysEnvRec env;
3689         short savev;
3690         long saved;
3691
3692         bool oops;
3693
3694 #endif /* !TARGET_API_MAC_CARBON */
3695
3696
3697         /*** Default values ***/
3698
3699         /* Initialize (backwards) */
3700         for (i = MAX_TERM_DATA - 1; i >= 0; i--)
3701         {
3702                 int n;
3703
3704                 cptr s;
3705
3706                 /* Obtain */
3707                 td = &data[i];
3708
3709                 /* Defaults */
3710                 term_data_hack(td);
3711
3712                 /* Obtain title */
3713                 s = angband_term_name[i];
3714
3715                 /* Get length */
3716                 n = strlen(s);
3717
3718                 /* Maximal length */
3719                 if (n > 15) n = 15;
3720
3721                 /* Copy the title */
3722                 strncpy((char*)(td->title) + 1, s, n);
3723
3724                 /* Save the length */
3725                 td->title[0] = n;
3726
3727                 /* Tile the windows */
3728                 td->r.left += (b * 30);
3729                 td->r.top += (b * 30);
3730
3731                 /* Tile */
3732                 b++;
3733         }
3734
3735
3736         /*** Load preferences ***/
3737         
3738 #if TARGET_API_MAC_CARBON
3739         cf_load_prefs();
3740 #else
3741         /* Assume failure */
3742         oops = TRUE;
3743
3744         /* Assume failure */
3745         fff = NULL;
3746
3747 #ifdef USE_SFL_CODE
3748
3749         /* Block */
3750         if (TRUE)
3751         {
3752                 OSErr   err;
3753                 short   vref;
3754                 long    dirID;
3755                 char    foo[128];
3756
3757                 /* Find the folder */
3758                 err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
3759                                  &vref, &dirID);
3760
3761                 /* Success */
3762                 if (!err)
3763                 {
3764                         /* Extract a path name */
3765                         PathNameFromDirID(dirID, vref, (StringPtr)foo);
3766
3767                         /* Convert the string */
3768                         ptocstr((StringPtr)foo);
3769
3770                         /* Append the preference file name */
3771                         strcat(foo, PREF_FILE_NAME);
3772
3773                         /* Open the preference file */
3774                         fff = fopen(foo, "r");
3775
3776                         /* Success */
3777                         oops = FALSE;
3778                 }
3779         }
3780
3781 #endif /* USE_SFL_CODE */
3782
3783         /* Oops */
3784         if (oops)
3785         {
3786                 /* Save */
3787                 HGetVol(0, &savev, &saved);
3788
3789                 /* Go to the "system" folder */
3790                 SysEnvirons(curSysEnvVers, &env);
3791                 SetVol(0, env.sysVRefNum);
3792
3793                 /* Open the file */
3794                 fff = fopen(PREF_FILE_NAME, "r");
3795
3796                 /* Restore */
3797                 HSetVol(0, savev, saved);
3798         }
3799
3800         /* Load preferences */
3801         if (fff)
3802         {
3803                 /* Load a real preference file */
3804                 load_prefs();
3805
3806                 /* Close the file */
3807                 my_fclose(fff);
3808         }
3809 #endif /* TARGET_API_MAC_CARBON */
3810
3811
3812         /*** Instantiate ***/
3813
3814         /* Main window */
3815         td = &data[0];
3816
3817         /* Many keys */
3818         td->keys = 1024;
3819
3820         /* Start visible */
3821         td->mapped = TRUE;
3822
3823         /* Link (backwards, for stacking order) */
3824         for (i = MAX_TERM_DATA - 1; i >= 0; i--)
3825         {
3826                 term_data_link(i);
3827         }
3828
3829         /* Main window */
3830         td = &data[0];
3831
3832         /* Main window */
3833         Term_activate(td->t);
3834 }
3835
3836 #ifndef MACH_O_CARBON
3837
3838 static void init_sound( void )
3839 {
3840         int err, i;
3841         CInfoPBRec pb;
3842         SignedByte              permission = fsRdPerm;
3843         pascal short    ret;
3844         
3845         Handle handle;
3846         Str255 sound;
3847
3848         /* Descend into "lib" folder */
3849         pb.dirInfo.ioCompletion = NULL;
3850         pb.dirInfo.ioNamePtr = "\plib";
3851         pb.dirInfo.ioVRefNum = app_vol;
3852         pb.dirInfo.ioDrDirID = app_dir;
3853         pb.dirInfo.ioFDirIndex = 0;
3854
3855         /* Check for errors */
3856         err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3857
3858         /* Success */
3859         if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3860         {
3861                 /* Descend into "lib/save" folder */
3862                 pb.dirInfo.ioCompletion = NULL;
3863                 pb.dirInfo.ioNamePtr = "\pxtra";
3864                 pb.dirInfo.ioVRefNum = app_vol;
3865                 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3866                 pb.dirInfo.ioFDirIndex = 0;
3867
3868                 /* Check for errors */
3869                 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3870                         
3871                         /* Success */
3872                 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3873                 {
3874                         /* Descend into "lib/save" folder */
3875                         pb.dirInfo.ioCompletion = NULL;
3876                         pb.dirInfo.ioNamePtr = "\psound";
3877                         pb.dirInfo.ioVRefNum = app_vol;
3878                         pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3879                         pb.dirInfo.ioFDirIndex = 0;
3880
3881                         /* Check for errors */
3882                         err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3883
3884                         /* Success */
3885                         if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3886                         {
3887                                 ret = HOpenResFile( app_vol , pb.dirInfo.ioDrDirID , "\psound.rsrc" , permission );
3888                                 if( ret != -1 ){
3889                                         ext_sound = 1;
3890                                         
3891                                         for( i = 0 ; i < 7 ; i++ )
3892                                                         soundmode[i] = false;
3893                                         
3894                                         for( i = 1 ; i < SOUND_MAX ; i++ ){
3895                                                 /* Get the proper sound name */
3896                                                 sprintf((char*)sound + 1, "%.16s.wav", angband_sound_name[i]);
3897                                                 sound[0] = strlen((char*)sound + 1);
3898
3899                                                 /* Obtain resource XXX XXX XXX */
3900                                                 handle = Get1NamedResource('snd ', sound);
3901                                                 if( handle == NULL || ext_sound )
3902                                                         handle = GetNamedResource('snd ', sound);
3903                                                 
3904                                                 if( handle )
3905                                                         soundmode[soundchoice[i]] = true;
3906                                                 
3907                                         }
3908                                 }
3909                         }
3910                 }
3911         }
3912 }
3913
3914 static void init_graf( void )
3915 {
3916         int err, i;
3917         CInfoPBRec pb;
3918         SignedByte              permission = fsRdPerm;
3919         pascal short    ret;
3920         
3921         Handle handle;
3922         Str255 graf;
3923
3924         /* Descend into "lib" folder */
3925         pb.dirInfo.ioCompletion = NULL;
3926         pb.dirInfo.ioNamePtr = "\plib";
3927         pb.dirInfo.ioVRefNum = app_vol;
3928         pb.dirInfo.ioDrDirID = app_dir;
3929         pb.dirInfo.ioFDirIndex = 0;
3930
3931         /* Check for errors */
3932         err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3933
3934         /* Success */
3935         if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3936         {
3937                 /* Descend into "lib/xtra" folder */
3938                 pb.dirInfo.ioCompletion = NULL;
3939                 pb.dirInfo.ioNamePtr = "\pxtra";
3940                 pb.dirInfo.ioVRefNum = app_vol;
3941                 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3942                 pb.dirInfo.ioFDirIndex = 0;
3943
3944                 /* Check for errors */
3945                 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3946                         
3947                 /* Success */
3948                 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3949                 {
3950                         /* Descend into "lib/xtra/graf" folder */
3951                         pb.dirInfo.ioCompletion = NULL;
3952                         pb.dirInfo.ioNamePtr = "\pgraf";
3953                         pb.dirInfo.ioVRefNum = app_vol;
3954                         pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3955                         pb.dirInfo.ioFDirIndex = 0;
3956
3957                         /* Check for errors */
3958                         err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3959
3960                         /* Success */
3961                         if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3962                         {
3963                                 ret = HOpenResFile( app_vol , pb.dirInfo.ioDrDirID , "\pgraf.rsrc" , permission );
3964                                 if (ret != -1)
3965                                 {
3966                                         ext_graf = 1;
3967
3968                                         /* Obtain resource XXX XXX XXX */
3969                                         handle = Get1NamedResource('PICT', graf);
3970                                         if ( handle == NULL || ext_graf )
3971                                                 handle = GetNamedResource('PICT', "\pgraf.rsrc");
3972                                 }
3973                         }
3974                 }
3975         }
3976 }
3977
3978 #endif /* MACH_O_CARBON */
3979
3980 #ifdef CHUUKEI
3981 /*
3982
3983 */
3984 static void init_chuukei( void )
3985 {
3986         char path[1024];
3987         char tmp[1024];
3988         FILE *fp;
3989         
3990         path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "chuukei.txt");
3991
3992         fp = fopen(path, "r");
3993         if(!fp)
3994                 return;
3995         
3996         /* Read a line */
3997         if (fgets(tmp, 1024, fp)){
3998                 if(tmp[0] == '-'){
3999                         int n = strlen(tmp);
4000                         tmp[n-1] = 0;
4001                         switch(tmp[1]){
4002                         case 'p':
4003                         {
4004                                 if (!tmp[2]) break;
4005                                 chuukei_server = TRUE;
4006                                 if(connect_chuukei_server(&tmp[2])<0){
4007                                         msg_print("connect fail");
4008                                         return;
4009                                 }
4010                                 msg_print("connect");
4011                                 msg_print(NULL);
4012                                 break;
4013                         }
4014
4015                         case 'c':
4016                         {
4017                                 chuukei_client = TRUE;
4018                                 connect_chuukei_server(&tmp[2]);
4019                                 play_game(FALSE);
4020                                 quit(NULL);
4021                         }
4022                         }
4023                 }
4024                 
4025         }
4026         fclose(fp);
4027         
4028 }
4029 #endif
4030
4031 /*
4032
4033 */
4034 short InevrtCheck( DialogPtr targetDlg, short check )
4035 {
4036         Handle  checkH;
4037         short   itemType;
4038         long    result;
4039         Rect    box;
4040         
4041         GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
4042         result = (GetControlValue( (ControlHandle)checkH ) + 1 ) % 2;
4043         SetControlValue( (ControlHandle)checkH , result );
4044         return result ;
4045
4046 }
4047
4048 /*
4049
4050 */
4051 short SetCheck( DialogPtr targetDlg, short check, long result )
4052 {
4053         Handle  checkH;
4054         short   itemType;
4055
4056         Rect    box;
4057         
4058         GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
4059         SetControlValue( (ControlHandle)checkH , result );
4060         return result ;
4061
4062 }
4063
4064 /*
4065
4066 */
4067 short GetCheck( DialogPtr targetDlg, short check )
4068 {
4069         Handle  checkH;
4070         short   itemType;
4071         long    result;
4072         Rect    box;
4073         
4074         GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
4075         result = GetControlValue( (ControlHandle)checkH );
4076         return result ;
4077
4078 }
4079 void SoundConfigDLog(void)
4080 {
4081         DialogPtr dialog;
4082         short item_hit;
4083         int     i;
4084
4085         dialog=GetNewDialog(131, 0, (WindowPtr)-1);
4086         SetDialogDefaultItem( dialog, ok );
4087         SetDialogCancelItem( dialog, cancel );
4088         for( i = 1 ; i < 7 ; i++ )
4089                 SetCheck( dialog, i+2 , soundmode[i] );
4090         
4091         /* ShowWindow(dialog); */ 
4092         for( item_hit = 100 ; cancel < item_hit ; ){
4093                 ModalDialog(0, &item_hit);
4094                 
4095                 switch(item_hit){
4096                         case ok:
4097                                 for( i = 1 ; i < 7 ; i++ )
4098                                         soundmode[i] = GetCheck( dialog, i+2 );
4099                                 break;
4100                         case cancel:
4101                                 break;
4102                         default:
4103                                 InevrtCheck( dialog, item_hit );
4104                 }
4105         }
4106         DisposeDialog(dialog);
4107
4108 }
4109
4110
4111 /*
4112  * Exit the program
4113  */
4114 #if TARGET_API_MAC_CARBON
4115 static void save_pref_file(void)
4116 {
4117         cf_save_prefs();
4118 }
4119 #else
4120 static void save_pref_file(void)
4121 {
4122         bool oops;
4123
4124         SysEnvRec env;
4125         short savev;
4126         long saved;
4127
4128
4129         /* Assume failure */
4130         oops = TRUE;
4131
4132         /* Assume failure */
4133         fff = NULL;
4134
4135         /* Text file */
4136         _ftype = 'TEXT';
4137
4138
4139 #ifdef USE_SFL_CODE
4140
4141         /* Block */
4142         if (TRUE)
4143         {
4144                 OSErr   err;
4145                 short   vref;
4146                 long    dirID;
4147                 char    foo[128];
4148
4149                 /* Find the folder */
4150                 err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
4151                                  &vref, &dirID);
4152
4153                 /* Success */
4154                 if (!err)
4155                 {
4156                         /* Extract a path name */
4157                         PathNameFromDirID(dirID, vref, (StringPtr)foo);
4158
4159                         /* Convert the string */
4160                         ptocstr((StringPtr)foo);
4161
4162                         /* Append the preference file name */
4163                         strcat(foo, PREF_FILE_NAME);
4164
4165                         /* Open the preference file */
4166                         /* my_fopen set file type and file creator for MPW */
4167                         fff = my_fopen(foo, "w");
4168
4169                         /* Success */
4170                         oops = FALSE;
4171                 }
4172         }
4173
4174 #endif /* USE_SFL_CODE */
4175
4176         /* Oops */
4177         if (oops)
4178         {
4179                 /* Save */
4180                 HGetVol(0, &savev, &saved);
4181
4182                 /* Go to "system" folder */
4183                 SysEnvirons(curSysEnvVers, &env);
4184                 SetVol(0, env.sysVRefNum);
4185
4186                 /* Open the preference file */
4187                 /* my_fopen set file type and file creator for MPW */
4188                 fff = fopen(PREF_FILE_NAME, "w");
4189
4190                 /* Restore */
4191                 HSetVol(0, savev, saved);
4192         }
4193
4194         /* Save preferences */
4195         if (fff)
4196         {
4197                 /* Write the preferences */
4198                 save_prefs();
4199
4200                 /* Close it */
4201                 my_fclose(fff);
4202         }
4203 }
4204 #endif
4205
4206
4207
4208 #if defined(__MWERKS__)
4209
4210 /*
4211  * A simple "Yes/No" filter to parse "key press" events in dialog windows
4212  */
4213 static pascal Boolean ynfilter(DialogPtr dialog, EventRecord *event, short *ip)
4214 {
4215         /* Parse key press events */
4216         if (event->what == keyDown)
4217         {
4218                 int i = 0;
4219                 char c;
4220
4221                 /* Extract the pressed key */
4222                 c = (event->message & charCodeMask);
4223
4224                 /* Accept "no" and <return> and <enter> */
4225                 if ((c=='n') || (c=='N') || (c==13) || (c==3)) i = 1;
4226
4227                 /* Accept "yes" */
4228                 else if ((c=='y') || (c=='Y')) i = 2;
4229
4230                 /* Handle "yes" or "no" */
4231                 if (i)
4232                 {
4233                         short type;
4234                         ControlHandle control;
4235                         Rect r;
4236
4237                         /* Get the button */
4238                         GetDialogItem(dialog, i, &type, (Handle*)&control, &r);
4239
4240                         /* Blink button for 1/10 second */
4241                         HiliteControl(control, 1);
4242                         Term_xtra_mac(TERM_XTRA_DELAY, 100);
4243                         HiliteControl(control, 0);
4244
4245                         /* Result */
4246                         *ip = i;
4247                         return (1);
4248                 }
4249         }
4250
4251         /* Ignore */
4252         return (0);
4253 }
4254
4255 #endif /* __MWERKS__ */
4256
4257
4258 #if TARGET_API_MAC_CARBON
4259
4260 /*
4261  * Prepare savefile dialogue and set the variable
4262  * savefile accordingly. Returns true if it succeeds, false (or
4263  * aborts) otherwise. If all is false, only allow files whose type
4264  * is 'SAVE'.
4265  * Originally written by Peter Ammon
4266  */
4267 static bool select_savefile(bool all)
4268 {
4269         OSErr err;
4270         FSSpec theFolderSpec;
4271         FSSpec savedGameSpec;
4272         NavDialogOptions dialogOptions;
4273         NavReplyRecord reply;
4274         /* Used only when 'all' is true */
4275         NavTypeList types = {ANGBAND_CREATOR, 1, 1, {'SAVE'}};
4276         NavTypeListHandle myTypeList;
4277         AEDesc defaultLocation;
4278
4279 #ifdef MACH_O_CARBON
4280
4281         /* Find the save folder */
4282         err = path_to_spec(ANGBAND_DIR_SAVE, &theFolderSpec);
4283
4284 #else
4285
4286         /* Find :lib:save: folder */
4287         err = FSMakeFSSpec(app_vol, app_dir, "\p:lib:save:", &theFolderSpec);
4288
4289 #endif
4290
4291         /* Oops */
4292         if (err != noErr) quit("Unable to find the folder :lib:save:");
4293
4294         /* Get default Navigator dialog options */
4295         err = NavGetDefaultDialogOptions(&dialogOptions);
4296
4297         /* Clear preview option */
4298         dialogOptions.dialogOptionFlags &= ~kNavAllowPreviews;
4299
4300         /* Disable multiple file selection */
4301         dialogOptions.dialogOptionFlags &= ~kNavAllowMultipleFiles;
4302
4303         /* Make descriptor for default location */
4304         err = AECreateDesc(typeFSS, &theFolderSpec, sizeof(FSSpec),
4305                 &defaultLocation);
4306
4307         /* Oops */
4308         if (err != noErr) quit("Unable to allocate descriptor");
4309
4310         /* We are indifferent to signature and file types */
4311         if (all)
4312         {
4313                 myTypeList = (NavTypeListHandle)nil;
4314         }
4315
4316         /* Set up type handle */
4317         else
4318         {
4319                 err = PtrToHand(&types, (Handle *)&myTypeList, sizeof(NavTypeList));
4320
4321                 /* Oops */
4322                 if (err != noErr) quit("Error in PtrToHand. Try enlarging heap");
4323
4324         }
4325
4326         /* Call NavGetFile() with the types list */
4327         err = NavChooseFile(&defaultLocation, &reply, &dialogOptions, NULL,
4328                 NULL, NULL, myTypeList, NULL);
4329
4330         /* Free type list */
4331         if (!all) DisposeHandle((Handle)myTypeList);
4332
4333         /* Error */
4334         if (err != noErr)
4335         {
4336                 /* Nothing */
4337         }
4338
4339         /* Invalid response -- allow the user to cancel */
4340         else if (!reply.validRecord)
4341         {
4342                 /* Hack -- Fake error */
4343                 err = -1;
4344         }
4345
4346         /* Retrieve FSSpec from the reply */
4347         else
4348         {
4349                 AEKeyword theKeyword;
4350                 DescType actualType;
4351                 Size actualSize;
4352
4353                 /* Get a pointer to selected file */
4354                 (void)AEGetNthPtr(&reply.selection, 1, typeFSS, &theKeyword,
4355                         &actualType, &savedGameSpec, sizeof(FSSpec), &actualSize);
4356
4357                 /* Dispose NavReplyRecord, resources and descriptors */
4358                 (void)NavDisposeReply(&reply);
4359         }
4360
4361         /* Dispose location info */
4362         AEDisposeDesc(&defaultLocation);
4363
4364         /* Error */
4365         if (err != noErr) return (FALSE);
4366
4367 #ifdef MACH_O_CARBON
4368
4369         /* Convert FSSpec to pathname and store it in variable savefile */
4370         (void)spec_to_path(&savedGameSpec, savefile, sizeof(savefile));
4371
4372 #else
4373
4374         /* Convert FSSpec to pathname and store it in variable savefile */
4375         refnum_to_name(
4376                 savefile,
4377                 savedGameSpec.parID,
4378                 savedGameSpec.vRefNum,
4379                 (char *)savedGameSpec.name);
4380
4381 #endif
4382
4383         /* Success */
4384         return (TRUE);
4385 }
4386 #endif
4387
4388
4389 /*
4390  * Handle menu: "File" + "New"
4391  */
4392 static void do_menu_file_new(void)
4393 {
4394         /* Hack */
4395         HiliteMenu(0);
4396
4397         /* Game is in progress */
4398         game_in_progress = 1;
4399
4400         /* Flush input */
4401         flush();
4402
4403         /* Play a game */
4404         play_game(TRUE);
4405
4406         /* Hack -- quit */
4407         quit(NULL);
4408 }
4409
4410
4411 /*
4412  * Handle menu: "File" + "Open"
4413  */
4414 #if TARGET_API_MAC_CARBON
4415 static void do_menu_file_open(bool all)
4416 {
4417         /* Let the player to choose savefile */
4418         if (!select_savefile(all)) return;
4419
4420         /* Hack */
4421         HiliteMenu(0);
4422
4423         /* Game is in progress */
4424         game_in_progress = TRUE;
4425
4426         /* Flush input */
4427         flush();
4428
4429         /* Play a game */
4430         play_game(FALSE);
4431
4432         /* Hack -- quit */
4433         quit(NULL);
4434 }
4435 #else
4436 static void do_menu_file_open(bool all)
4437 {
4438         int err;
4439         short vrefnum;
4440         long drefnum;
4441         long junk;
4442         DirInfo pb;
4443         SFTypeList types;
4444         SFReply reply;
4445         Point topleft;
4446
4447
4448         /* XXX XXX XXX */
4449
4450         /* vrefnum = GetSFCurVol(); */
4451         vrefnum = -*((short*)0x214);
4452
4453         /* drefnum = GetSFCurDir(); */
4454         drefnum = *((long*)0x398);
4455
4456         /* Descend into "lib" folder */
4457         pb.ioCompletion = NULL;
4458         pb.ioNamePtr = "\plib";
4459         pb.ioVRefNum = vrefnum;
4460         pb.ioDrDirID = drefnum;
4461         pb.ioFDirIndex = 0;
4462
4463         /* Check for errors */
4464         err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
4465
4466         /* Success */
4467         if ((err == noErr) && (pb.ioFlAttrib & 0x10))
4468         {
4469                 /* Descend into "lib/save" folder */
4470                 pb.ioCompletion = NULL;
4471                 pb.ioNamePtr = "\psave";
4472                 pb.ioVRefNum = vrefnum;
4473                 pb.ioDrDirID = pb.ioDrDirID;
4474                 pb.ioFDirIndex = 0;
4475
4476                 /* Check for errors */
4477                 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
4478
4479                 /* Success */
4480                 if ((err == noErr) && (pb.ioFlAttrib & 0x10))
4481                 {
4482                         /* SetSFCurDir(pb.ioDrDirID); */
4483                         *((long*)0x398) = pb.ioDrDirID;
4484                 }
4485         }
4486
4487         /* Window location */
4488         topleft.h = (qd.screenBits.bounds.left+qd.screenBits.bounds.right)/2-344/2;
4489         topleft.v = (2*qd.screenBits.bounds.top+qd.screenBits.bounds.bottom)/3-188/2;
4490
4491         /* Allow "all" files */
4492         if (all)
4493         {
4494                 /* Get any file */
4495                 SFGetFile(topleft, "\p", NULL, -1, types, NULL, &reply);
4496         }
4497
4498         /* Allow "save" files */
4499         else
4500         {
4501                 /* Legal types */
4502                 types[0] = 'SAVE';
4503
4504                 /* Get a file */
4505                 SFGetFile(topleft, "\p", NULL, 1, types, NULL, &reply);
4506         }
4507
4508         /* Allow cancel */
4509         if (!reply.good) return;
4510
4511         /* Extract textual file name for save file */
4512         GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
4513         refnum_to_name(savefile, drefnum, vrefnum, (char*)reply.fName);
4514
4515         /* Hack */
4516         HiliteMenu(0);
4517
4518         /* Game is in progress */
4519         game_in_progress = 1;
4520
4521         /* Flush input */
4522         flush();
4523
4524         /* Play a game */
4525         play_game(FALSE);
4526
4527         /* Hack -- quit */
4528         quit(NULL);
4529 }
4530 #endif
4531
4532
4533 /*
4534  * Handle the "open_when_ready" flag
4535  */
4536 static void handle_open_when_ready(void)
4537 {
4538         /* Check the flag XXX XXX XXX make a function for this */
4539         if (open_when_ready && initialized && !game_in_progress)
4540         {
4541                 /* Forget */
4542                 open_when_ready = FALSE;
4543
4544                 /* Game is in progress */
4545                 game_in_progress = 1;
4546
4547                 /* Wait for it */
4548                 pause_line(23);
4549
4550                 /* Flush input */
4551                 flush();
4552
4553                 /* Play a game */
4554                 play_game(FALSE);
4555
4556                 /* Quit */
4557                 quit(NULL);
4558         }
4559 }
4560
4561
4562
4563 /*
4564  * Initialize the menus
4565  *
4566  *   Apple (128) =   { About, -, ... }
4567  *   File (129) =    { New,Open,Import,Close,Save,-,Exit,Quit }
4568  *   Edit (130) =    { Cut, Copy, Paste, Clear }   (?)
4569  *   Font (131) =    { Bold, Extend, -, Monaco, ..., -, ... }
4570  *   Size (132) =    { ... }
4571  *   Window (133) =  { Angband, Mirror, Recall, Choice,
4572  *                     Term-4, Term-5, Term-6, Term-7 }
4573  *   Special (134) = { Sound, Graphics, TileWidth, TileHeight, -,
4574  *                     Fiddle, Wizard }
4575  */
4576
4577 /* Apple menu */
4578 #define MENU_APPLE      128
4579 #define ITEM_ABOUT      1
4580
4581 /* File menu */
4582 #define MENU_FILE       129
4583 # define ITEM_NEW       1
4584 # define ITEM_OPEN      2
4585 # define ITEM_IMPORT    3
4586 # define ITEM_CLOSE     4
4587 # define ITEM_SAVE      5
4588 #  define ITEM_QUIT     7
4589
4590 /* Edit menu */
4591 #define MENU_EDIT       130
4592 # define ITEM_UNDO      1
4593 # define ITEM_CUT       3
4594 # define ITEM_COPY      4
4595 # define ITEM_PASTE     5
4596 # define ITEM_CLEAR     6
4597
4598 /* Font menu */
4599 #define MENU_FONT       131
4600 # define ITEM_BOLD      1
4601 # define ITEM_WIDE      2
4602
4603 /* Size menu */
4604 #define MENU_SIZE       132
4605
4606 /* Windows menu */
4607 #define MENU_WINDOWS    133
4608
4609 /* Special menu */
4610 #define MENU_SPECIAL    134
4611 # define ITEM_SOUND     1
4612 # define ITEM_GRAPH     2
4613 # define ITEM_TILEWIDTH 3
4614 # define ITEM_TILEHEIGHT 4
4615 # define ITEM_FIDDLE    6
4616 # define ITEM_WIZARD    7
4617
4618 /* Sounds submenu */
4619 #define SUBMENU_SOUND   143
4620 # define ITEM_USE_SOUND 1
4621 # define ITEM_SOUND_SETTING     2
4622
4623 /* Graphics submenu */
4624 #define SUBMENU_GRAPH   144
4625 # define ITEM_NONE      1
4626 # define ITEM_8X8       2
4627 # define ITEM_16X16     3
4628 # define ITEM_BIGTILE 5 
4629
4630 /* TileWidth submenu */
4631 #define SUBMENU_TILEWIDTH       145
4632
4633 /* TileHeight submenu */
4634 #define SUBMENU_TILEHEIGHT      146
4635
4636
4637 static void init_menubar(void)
4638 {
4639         int i, n;
4640
4641         Rect r;
4642
4643         WindowPtr tmpw;
4644
4645         MenuHandle m;
4646
4647         Handle mbar;
4648
4649 #if TARGET_API_MAC_CARBON
4650         OSErr err;
4651         long response;
4652 #endif
4653
4654         /* Get the "apple" menu */
4655         mbar = GetNewMBar(128);
4656
4657         /* Whoops! */
4658 #ifdef JP
4659         if (mbar == nil) quit("¥á¥Ë¥å¡¼¥Ð¡¼ ID 128¤ò¸«¤Ä¤±¤ë»ö¤¬¤Ç¤­¤Þ¤»¤ó!");
4660 #else
4661         if (mbar == nil) quit("Cannot find menubar('MBAR') id 128!");
4662 #endif
4663
4664         /* Insert them into the current menu list */
4665         SetMenuBar(mbar);
4666
4667         /* Free handle */
4668         DisposeHandle(mbar);
4669
4670 #if !TARGET_API_MAC_CARBON
4671         /* Apple menu (id 128) */
4672         m = GetMenuHandle(MENU_APPLE);
4673
4674         /* Add the DA's to the "apple" menu */
4675         AppendResMenu   (m, 'DRVR');
4676 #endif
4677
4678         /* Get the "File" menu */
4679 #if TARGET_API_MAC_CARBON
4680         m = GetMenuHandle(MENU_FILE);
4681         err = Gestalt( gestaltSystemVersion, &response );
4682         if ( (err == noErr) && (response >= 0x00000A00) )
4683         {
4684                 DeleteMenuItem(m, ITEM_QUIT);
4685         }
4686 #endif
4687
4688         /* Edit menu (id 130) - we don't have to do anything */
4689
4690         /*
4691          * Font menu (id 131) - append names of mono-spaced fonts
4692          * followed by all available ones
4693          */
4694         m = GetMenuHandle(MENU_FONT);
4695
4696         /* Fake window */
4697         r.left = r.right = r.top = r.bottom = 0;
4698
4699         /* Make the fake window */
4700         tmpw = NewWindow(0, &r, "\p", false, documentProc, 0, 0, 0);
4701
4702         /* Activate the "fake" window */
4703 #if TARGET_API_MAC_CARBON
4704         SetPortWindowPort(tmpw);
4705 #else
4706         SetPort(tmpw);
4707 #endif
4708
4709         /* Default mode */
4710         TextMode(0);
4711
4712         /* Default size */
4713         TextSize(12);
4714
4715         /* Add the fonts to the menu */
4716         AppendResMenu(m, 'FONT');
4717
4718         /* Size of menu */
4719 #if TARGET_API_MAC_CARBON
4720         n = CountMenuItems(m);
4721 #else
4722         n = CountMItems(m);
4723 #endif
4724
4725         /* Scan the menu */
4726         for (i = n; i >= 4; i--)
4727         {
4728                 Str255 tmpName;
4729                 short fontNum;
4730
4731                 /* Acquire the font name */
4732                 GetMenuItemText(m, i, tmpName);
4733
4734                 /* Acquire the font index */
4735 #if TARGET_API_MAC_CARBON
4736                 fontNum = FMGetFontFamilyFromName( tmpName );
4737 #else
4738                 GetFNum(tmpName, &fontNum);
4739 #endif
4740
4741                 /* Apply the font index */
4742                 TextFont(fontNum);
4743
4744                 /* Remove non-mono-spaced fonts */
4745                 if ((CharWidth('i') != CharWidth('W')) || (CharWidth('W') == 0))
4746                 {
4747                         /* Delete the menu item XXX XXX XXX */
4748                         DeleteMenuItem  (m, i);
4749                 }
4750         }
4751
4752         /* Destroy the old window */
4753         DisposeWindow(tmpw);
4754
4755         /* Add a separator */
4756         AppendMenu(m, "\p-");
4757
4758         /* Add the fonts to the menu */
4759         AppendResMenu   (m, 'FONT');
4760
4761
4762         /* Size menu (id 132) */
4763         m = GetMenuHandle(MENU_SIZE);
4764
4765         /* Add some sizes (stagger choices) */
4766         for (i = 8; i <= 32; i += ((i / 16) + 1))
4767         {
4768                 Str15 buf;
4769                 
4770                 /* Textual size */
4771                 sprintf((char*)buf + 1, "%d", i);
4772                 buf[0] = strlen((char*)buf + 1);
4773
4774                 /* Add the item */
4775                 AppendMenu(m, buf);
4776         }
4777
4778
4779         /* Windows menu (id 133) */
4780         m = GetMenuHandle(MENU_WINDOWS);
4781
4782         /* Default choices */
4783         for (i = 0; i < MAX_TERM_DATA; i++)
4784         {
4785                 Str15 buf;
4786                 
4787                 /* Describe the item */
4788                 sprintf((char*)buf + 1, "%.15s", angband_term_name[i]);
4789                 buf[0] = strlen((char*)buf + 1);
4790
4791                 /* Add the item */
4792                 AppendMenu(m, buf);
4793
4794                 /* Command-Key shortcuts */
4795                 if (i < 8) SetItemCmd(m, i + 1, '0' + i);
4796         }
4797
4798
4799 #if TARGET_API_MAC_CARBON && !defined(MAC_MPW)
4800
4801         /* CW or gcc -- Use recommended interface for hierarchical menus */
4802
4803         /* Special menu (id 134) */
4804         m = GetMenuHandle(MENU_SPECIAL);
4805
4806         /* Insert Graphics submenu (id 143) */
4807         {
4808                 MenuHandle submenu;
4809
4810                 /* Get the submenu */
4811                 submenu = GetMenu(SUBMENU_SOUND);
4812
4813                 /* Insert it */
4814                 SetMenuItemHierarchicalMenu(m, ITEM_SOUND, submenu);
4815         }
4816
4817         /* Insert Graphics submenu (id 144) */
4818         {
4819                 MenuHandle submenu;
4820
4821                 /* Get the submenu */
4822                 submenu = GetMenu(SUBMENU_GRAPH);
4823
4824                 /* Insert it */
4825                 SetMenuItemHierarchicalMenu(m, ITEM_GRAPH, submenu);
4826         }
4827
4828         /* Insert TileWidth submenu (id 145) */
4829         {
4830                 MenuHandle submenu;
4831
4832                 /* Get the submenu */
4833                 submenu = GetMenu(SUBMENU_TILEWIDTH);
4834
4835                 /* Add some sizes */
4836                 for (i = 4, n = 1; i <= 32; i++, n++)
4837                 {
4838                         Str15 buf;
4839
4840                         /* Textual size */
4841                         strnfmt((char*)buf + 1, 15, "%d", i);
4842                         buf[0] = strlen((char*)buf + 1);
4843
4844                         /* Append item */
4845                         AppendMenu(submenu, buf);
4846                 }
4847
4848                 /* Insert it */
4849                 SetMenuItemHierarchicalMenu(m, ITEM_TILEWIDTH, submenu);
4850         }
4851
4852         /* Insert TileHeight submenu (id 146) */
4853         {
4854                 MenuHandle submenu;
4855
4856                 /* Get the submenu */
4857                 submenu = GetMenu(SUBMENU_TILEHEIGHT);
4858
4859
4860                 /* Add some sizes */
4861                 for (i = 4, n = 1; i <= 32; i++, n++)
4862                 {
4863                         Str15 buf;
4864
4865                         /* Textual size */
4866                         strnfmt((char*)buf + 1, 15, "%d", i);
4867                         buf[0] = strlen((char*)buf + 1);
4868
4869                         /* Append item */
4870                         AppendMenu(submenu, buf);
4871                 }
4872
4873                 /* Insert it */
4874                 SetMenuItemHierarchicalMenu(m, ITEM_TILEHEIGHT, submenu);
4875         }
4876
4877 #else
4878
4879         /* Special menu (id 134) */
4880
4881         /* Get graphics (sub)menu (id 143) */
4882         m = GetMenu(SUBMENU_SOUND);
4883
4884         /* Insert it as a submenu */            
4885         InsertMenu(m, hierMenu);
4886
4887
4888         /* Get graphics (sub)menu (id 144) */
4889         m = GetMenu(SUBMENU_GRAPH);
4890
4891         /* Insert it as a submenu */            
4892         InsertMenu(m, hierMenu);
4893
4894
4895         /* Get TileWidth (sub)menu (id 145) */
4896         m = GetMenu(SUBMENU_TILEWIDTH);
4897
4898         /* Add some sizes */
4899         for (i = 4; i <= 32; i++)
4900         {
4901                 Str15 buf;
4902                 
4903                 /* Textual size */
4904                 sprintf((char*)buf + 1, "%d", i);
4905                 buf[0] = strlen((char*)buf + 1);
4906
4907                 /* Append item */
4908                 AppendMenu(m, buf);
4909         }
4910
4911
4912         /* Insert it as a submenu */
4913         InsertMenu(m, hierMenu);
4914
4915         /* Get TileHeight (sub)menu (id 146) */
4916         m = GetMenu(SUBMENU_TILEHEIGHT);
4917
4918         /* Add some sizes */
4919         for (i = 4; i <= 32; i++)
4920         {
4921                 Str15 buf;
4922
4923                 /* Textual size */
4924                 sprintf((char*)buf + 1, "%d", i);
4925                 buf[0] = strlen((char*)buf + 1);
4926
4927                 /* Append item */
4928                 AppendMenu(m, buf);
4929         }
4930
4931
4932         /* Insert the menu */
4933         InsertMenu(m, hierMenu);
4934
4935 #endif
4936         /* Update the menu bar */
4937         DrawMenuBar();
4938 }
4939
4940
4941 /*
4942  * Prepare the menus
4943  */
4944 static void setup_menus(void)
4945 {
4946         int i, n;
4947
4948         short value;
4949
4950         Str255 s;
4951
4952         MenuHandle m;
4953
4954         term_data *td = NULL;
4955
4956
4957         /* Relevant "term_data" */
4958         for (i = 0; i < MAX_TERM_DATA; i++)
4959         {
4960                 /* Unused */
4961                 if (!data[i].t) continue;
4962
4963                 /* Notice the matching window */
4964                 if (data[i].w == FrontWindow()) td = &data[i];
4965         }
4966
4967
4968         /* File menu */
4969         m = GetMenuHandle(MENU_FILE);
4970
4971         /* Get menu size */
4972 #if TARGET_API_MAC_CARBON
4973         n = CountMenuItems(m);
4974 #else
4975         n = CountMItems(m);
4976 #endif
4977
4978         /* Reset menu */
4979         for (i = 1; i <= n; i++)
4980         {
4981                 /* Reset */
4982 #if TARGET_API_MAC_CARBON
4983                 DisableMenuItem(m, i);
4984                 CheckMenuItem(m, i, FALSE);
4985 #else
4986                 DisableItem(m, i);
4987                 CheckItem(m, i, FALSE);
4988 #endif
4989         }
4990
4991         /* Enable "new"/"open..."/"import..." */
4992         if (initialized && !game_in_progress)
4993         {
4994 #if TARGET_API_MAC_CARBON
4995                 EnableMenuItem(m, ITEM_NEW);
4996                 EnableMenuItem(m, ITEM_OPEN);
4997                 EnableMenuItem(m, ITEM_IMPORT);
4998 #else
4999                 EnableItem(m, ITEM_NEW);
5000                 EnableItem(m, ITEM_OPEN);
5001                 EnableItem(m, ITEM_IMPORT);
5002 #endif
5003         }
5004
5005         /* Enable "close" */
5006         if (initialized)
5007         {
5008 #if TARGET_API_MAC_CARBON
5009                 EnableMenuItem(m, ITEM_CLOSE);
5010 #else
5011                 EnableItem(m, ITEM_CLOSE);
5012 #endif
5013         }
5014
5015         /* Enable "save" */
5016         if (initialized && character_generated)
5017         {
5018 #if TARGET_API_MAC_CARBON
5019                 EnableMenuItem(m, ITEM_SAVE);
5020 #else
5021                 EnableItem(m, ITEM_SAVE);
5022 #endif
5023         }
5024
5025         /* Enable "quit" */
5026         if (TRUE)
5027         {
5028 #if TARGET_API_MAC_CARBON
5029                 EnableMenuItem(m, ITEM_QUIT);
5030 #else
5031                 EnableItem(m, ITEM_QUIT);
5032 #endif
5033         }
5034
5035
5036         /* Edit menu */
5037         m = GetMenuHandle(MENU_EDIT);
5038
5039         /* Get menu size */
5040 #if TARGET_API_MAC_CARBON
5041         n = CountMenuItems(m);
5042 #else
5043         n = CountMItems(m);
5044 #endif
5045
5046         /* Reset menu */
5047         for (i = 1; i <= n; i++)
5048         {
5049                 /* Reset */
5050 #if TARGET_API_MAC_CARBON
5051                 DisableMenuItem(m, i);
5052                 CheckMenuItem(m, i, FALSE);
5053 #else
5054                 DisableItem(m, i);
5055                 CheckItem(m, i, FALSE);
5056 #endif
5057         }
5058
5059         /* Enable "edit" options if "needed" */
5060         if (!td)
5061         {
5062 #if TARGET_API_MAC_CARBON
5063                 EnableMenuItem(m, ITEM_UNDO);
5064                 EnableMenuItem(m, ITEM_CUT);
5065                 EnableMenuItem(m, ITEM_COPY);
5066                 EnableMenuItem(m, ITEM_PASTE);
5067                 EnableMenuItem(m, ITEM_CLEAR);
5068 #else
5069                 EnableItem(m, ITEM_UNDO);
5070                 EnableItem(m, ITEM_CUT);
5071                 EnableItem(m, ITEM_COPY);
5072                 EnableItem(m, ITEM_PASTE);
5073                 EnableItem(m, ITEM_CLEAR);
5074 #endif
5075         }
5076
5077
5078         /* Font menu */
5079         m = GetMenuHandle(MENU_FONT);
5080
5081         /* Get menu size */
5082 #if TARGET_API_MAC_CARBON
5083         n = CountMenuItems(m);
5084 #else
5085         n = CountMItems(m);
5086 #endif
5087
5088         /* Reset menu */
5089         for (i = 1; i <= n; i++)
5090         {
5091                 /* Reset */
5092 #if TARGET_API_MAC_CARBON
5093                 DisableMenuItem(m, i);
5094                 CheckMenuItem(m, i, FALSE);
5095 #else
5096                 DisableItem(m, i);
5097                 CheckItem(m, i, FALSE);
5098 #endif
5099         }
5100
5101         /* Hack -- look cute XXX XXX */
5102         /* SetItemStyle(m, 1, bold); */
5103
5104         /* Hack -- look cute XXX XXX */
5105         /* SetItemStyle(m, 2, extend); */
5106
5107         /* Active window */
5108         if (td)
5109         {
5110 #if TARGET_API_MAC_CARBON
5111                 /* Enable "bold" */
5112                 EnableMenuItem(m, ITEM_BOLD);
5113
5114                 /* Enable "extend" */
5115                 EnableMenuItem(m, ITEM_WIDE);
5116
5117                 /* Check the appropriate "bold-ness" */
5118                 if (td->font_face & bold) CheckMenuItem(m, ITEM_BOLD, TRUE);
5119
5120                 /* Check the appropriate "wide-ness" */
5121                 if (td->font_face & extend) CheckMenuItem(m, ITEM_WIDE, TRUE);
5122
5123                 /* Analyze fonts */
5124                 for (i = 4; i <= n; i++)
5125                 {
5126                         /* Enable it */
5127                         EnableMenuItem(m, i);
5128
5129                         /* Analyze font */
5130                         GetMenuItemText(m, i, s);
5131                         GetFNum(s, &value);
5132
5133                         /* Check active font */
5134                         if (td->font_id == value) CheckMenuItem(m, i, TRUE);
5135                 }
5136 #else
5137                 /* Enable "bold" */
5138                 EnableItem(m, ITEM_BOLD);
5139
5140                 /* Enable "extend" */
5141                 EnableItem(m, ITEM_WIDE);
5142
5143                 /* Check the appropriate "bold-ness" */
5144                 if (td->font_face & bold) CheckItem(m, ITEM_BOLD, TRUE);
5145
5146                 /* Check the appropriate "wide-ness" */
5147                 if (td->font_face & extend) CheckItem(m, ITEM_WIDE, TRUE);
5148
5149                 /* Analyze fonts */
5150                 for (i = 4; i <= n; i++)
5151                 {
5152                         /* Enable it */
5153                         EnableItem(m, i);
5154
5155                         /* Analyze font */
5156                         GetMenuItemText(m, i, s);
5157                         GetFNum(s, &value);
5158
5159                         /* Check active font */
5160                         if (td->font_id == value) CheckItem(m, i, TRUE);
5161                 }
5162 #endif
5163         }
5164
5165
5166         /* Size menu */
5167         m = GetMenuHandle(MENU_SIZE);
5168
5169         /* Get menu size */
5170 #if TARGET_API_MAC_CARBON
5171         n = CountMenuItems(m);
5172 #else
5173         n = CountMItems(m);
5174 #endif
5175
5176         /* Reset menu */
5177         for (i = 1; i <= n; i++)
5178         {
5179                 /* Reset */
5180 #if TARGET_API_MAC_CARBON
5181                 DisableMenuItem(m, i);
5182                 CheckMenuItem(m, i, FALSE);
5183 #else
5184                 DisableItem(m, i);
5185                 CheckItem(m, i, FALSE);
5186 #endif
5187         }
5188         
5189         /* Active window */
5190         if (td)
5191         {
5192                 /* Analyze sizes */
5193                 for (i = 1; i <= n; i++)
5194                 {
5195                         /* Analyze size */
5196                         GetMenuItemText(m, i, s);
5197                         s[s[0]+1] = '\0';
5198                         value = atoi((char*)(s+1));
5199
5200 #if TARGET_API_MAC_CARBON
5201                         /* Enable the "real" sizes */
5202                         if (RealFont(td->font_id, value)) EnableMenuItem(m, i);
5203
5204                         /* Check the current size */
5205                         if (td->font_size == value) CheckMenuItem(m, i, TRUE);
5206 #else
5207                         /* Enable the "real" sizes */
5208                         if (RealFont(td->font_id, value)) EnableItem(m, i);
5209
5210                         /* Check the current size */
5211                         if (td->font_size == value) CheckItem(m, i, TRUE);
5212 #endif
5213                 }
5214         }
5215
5216
5217         /* Windows menu */
5218         m = GetMenuHandle(MENU_WINDOWS);
5219
5220         /* Get menu size */
5221 #if TARGET_API_MAC_CARBON
5222         n = CountMenuItems(m);
5223 #else
5224         n = CountMItems(m);
5225 #endif
5226
5227         /* Check active windows */
5228         for (i = 1; i <= n; i++)
5229         {
5230                 /* Check if needed */
5231 #if TARGET_API_MAC_CARBON
5232                 CheckMenuItem(m, i, data[i-1].mapped);
5233 #else
5234                 CheckItem(m, i, data[i-1].mapped);
5235 #endif
5236         }
5237
5238
5239         /* Special menu */
5240         m = GetMenuHandle(MENU_SPECIAL);
5241
5242         /* Get menu size */
5243 #if TARGET_API_MAC_CARBON
5244         n = CountMenuItems(m);
5245 #else
5246         n = CountMItems(m);
5247 #endif
5248
5249         /* Reset menu */
5250         for (i = 1; i <= n; i++)
5251         {
5252                 /* Reset */
5253 #if TARGET_API_MAC_CARBON
5254                 DisableMenuItem(m, i);
5255
5256 #ifdef MAC_MPW
5257                 /* XXX Oh no, this removes submenu... */
5258                 if ((i != ITEM_SOUND) &&
5259                     (i != ITEM_GRAPH) &&
5260                     (i != ITEM_TILEWIDTH) &&
5261                     (i != ITEM_TILEHEIGHT)) CheckMenuItem(m, i, FALSE);
5262 #else
5263
5264                 CheckMenuItem(m, i, FALSE);
5265 #endif
5266
5267 #else
5268                 DisableItem(m, i);
5269
5270                 /* XXX Oh no, this removes submenu... */
5271                 if ((i != ITEM_SOUND) &&
5272                     (i != ITEM_GRAPH) &&
5273                     (i != ITEM_TILEWIDTH) &&
5274                     (i != ITEM_TILEHEIGHT)) CheckItem(m, i, FALSE);
5275 #endif
5276         }
5277
5278 #if TARGET_API_MAC_CARBON
5279         /* Item "arg_sound" */
5280         EnableMenuItem(m, ITEM_SOUND);
5281         {
5282                 MenuRef submenu;
5283
5284 #ifdef MAC_MPW
5285
5286                 /* MPW's Universal Interface is a bit out of date */
5287
5288                 /* Graphics submenu */
5289                 submenu = GetMenuHandle(SUBMENU_SOUND);
5290
5291 #else
5292
5293                 /* Graphics submenu */
5294                 (void)GetMenuItemHierarchicalMenu(m, ITEM_SOUND, &submenu);
5295
5296 #endif
5297
5298                 /* Get menu size */
5299                 n = CountMenuItems(submenu);
5300
5301                 /* Reset menu */
5302                 for (i = 1; i <= n; i++)
5303                 {
5304                         /* Reset */
5305                         DisableMenuItem(submenu, i);
5306                         CheckMenuItem(submenu, i, FALSE);
5307                 }
5308
5309                 /* Item "Sound On/Off" */
5310                 EnableMenuItem(submenu, ITEM_USE_SOUND);
5311                 CheckMenuItem(submenu, ITEM_USE_SOUND, arg_sound);
5312
5313                 /* Item "Sounf Config" */
5314 #ifndef MACH_O_CARBON
5315                 EnableMenuItem(submenu, ITEM_SOUND_SETTING);
5316 #endif
5317         }
5318
5319         /* Item "Graphics" */
5320         EnableMenuItem(m, ITEM_GRAPH);
5321         {
5322                 MenuRef submenu;
5323
5324 #ifdef MAC_MPW
5325
5326                 /* MPW's Universal Interface is a bit out of date */
5327
5328                 /* Graphics submenu */
5329                 submenu = GetMenuHandle(SUBMENU_GRAPH);
5330
5331 #else
5332
5333                 /* Graphics submenu */
5334                 (void)GetMenuItemHierarchicalMenu(m, ITEM_GRAPH, &submenu);
5335
5336 #endif
5337
5338                 /* Get menu size */
5339                 n = CountMenuItems(submenu);
5340
5341                 /* Reset menu */
5342                 for (i = 1; i <= n; i++)
5343                 {
5344                         /* Reset */
5345                         DisableMenuItem(submenu, i);
5346                         CheckMenuItem(submenu, i, FALSE);
5347                 }
5348
5349                 /* Item "None" */
5350                 EnableMenuItem(submenu, ITEM_NONE);
5351                 CheckMenuItem(submenu, ITEM_NONE, (graf_mode == GRAF_MODE_NONE));
5352
5353                 /* Item "8x8" */
5354                 EnableMenuItem(submenu, ITEM_8X8);
5355                 CheckMenuItem(submenu, ITEM_8X8, (graf_mode == GRAF_MODE_8X8));
5356
5357                 /* Item "16x16" */
5358                 EnableMenuItem(submenu, ITEM_16X16);
5359                 CheckMenuItem(submenu, ITEM_16X16, (graf_mode == GRAF_MODE_16X16));
5360
5361                 /* Item "Big tiles" */
5362                 EnableMenuItem(submenu, ITEM_BIGTILE);
5363                 CheckMenuItem(submenu, ITEM_BIGTILE, arg_bigtile);
5364         }
5365
5366         /* Item "TileWidth" */
5367         EnableMenuItem(m, ITEM_TILEWIDTH);
5368         {
5369                 MenuRef submenu;
5370
5371 #ifdef MAC_MPW
5372
5373                 /* MPW's Universal Interface is a bit out of date */
5374
5375                 /* TIleWidth submenu */
5376                 submenu = GetMenuHandle(SUBMENU_TILEWIDTH);
5377
5378 #else
5379
5380                 /* TileWidth submenu */
5381                 (void)GetMenuItemHierarchicalMenu(m, ITEM_TILEWIDTH, &submenu);
5382
5383 #endif
5384
5385                 /* Get menu size */
5386                 n = CountMenuItems(submenu);
5387
5388                 /* Reset menu */
5389                 for (i = 1; i <= n; i++)
5390                 {
5391                         /* Reset */
5392                         DisableMenuItem(submenu, i);
5393                         CheckMenuItem(submenu, i, FALSE);
5394                 }
5395
5396                 /* Active window */
5397                 if (td)
5398                 {
5399                         /* Analyze sizes */
5400                         for (i = 1; i <= n; i++)
5401                         {
5402                                 /* Analyze size */
5403                                 /* GetMenuItemText(m,i,s); */
5404                                 GetMenuItemText(submenu, i, s);
5405                                 s[s[0]+1] = '\0';
5406                                 value = atoi((char*)(s+1));
5407
5408                                 /* Enable */
5409                                 if (value >= td->font_wid) EnableMenuItem(submenu, i);
5410
5411                                 /* Check the current size */
5412                                 if (td->tile_wid == value) CheckMenuItem(submenu, i, TRUE);
5413                         }
5414                 }
5415         }
5416
5417         /* Item "TileHeight" */
5418         EnableMenuItem(m, ITEM_TILEHEIGHT);
5419         {
5420                 MenuRef submenu;
5421
5422 #ifdef MAC_MPW
5423
5424                 /* MPW's Universal Interface is a bit out of date */
5425
5426                 /* TileHeight submenu */
5427                 submenu = GetMenuHandle(SUBMENU_TILEHEIGHT);
5428
5429 #else
5430
5431                 /* TileWidth submenu */
5432                 (void)GetMenuItemHierarchicalMenu(m, ITEM_TILEHEIGHT, &submenu);
5433
5434 #endif
5435
5436                 /* Get menu size */
5437                 n = CountMenuItems(submenu);
5438
5439                 /* Reset menu */
5440                 for (i = 1; i <= n; i++)
5441                 {
5442                         /* Reset */
5443                         DisableMenuItem(submenu, i);
5444                         CheckMenuItem(submenu, i, FALSE);
5445                 }
5446
5447                 /* Active window */
5448                 if (td)
5449                 {
5450                         /* Analyze sizes */
5451                         for (i = 1; i <= n; i++)
5452                         {
5453                                 /* Analyze size */
5454                                 /* GetMenuItemText(m,i,s); */
5455                                 GetMenuItemText(submenu, i, s);
5456                                 s[s[0]+1] = '\0';
5457                                 value = atoi((char*)(s+1));
5458
5459                                 /* Enable */
5460                                 if (value >= td->font_hgt) EnableMenuItem(submenu, i);
5461
5462                                 /* Check the current size */
5463                                 if (td->tile_hgt == value) CheckMenuItem(submenu, i, TRUE);
5464                         }
5465                 }
5466         }
5467
5468         /* Item "arg_fiddle" */
5469         EnableMenuItem(m, ITEM_FIDDLE);
5470         CheckMenuItem(m, ITEM_FIDDLE, arg_fiddle);
5471
5472         /* Item "arg_wizard" */
5473         EnableMenuItem(m, ITEM_WIZARD);
5474         CheckMenuItem(m, ITEM_WIZARD, arg_wizard);
5475
5476 #else
5477         /* Item "arg_sound" */
5478         EnableItem(m, ITEM_SOUND);
5479
5480         /* Item "arg_graphics" */
5481         EnableItem(m, ITEM_GRAPH);
5482
5483         /* Item "TileWidth" */
5484         EnableItem(m, ITEM_TILEWIDTH);
5485
5486         /* Item "TileHeight" */
5487         EnableItem(m, ITEM_TILEHEIGHT);
5488
5489         /* Item "arg_fiddle" */
5490         EnableItem(m, ITEM_FIDDLE);
5491         CheckItem(m, ITEM_FIDDLE, arg_fiddle);
5492
5493         /* Item "arg_wizard" */
5494         EnableItem(m, ITEM_WIZARD);
5495         CheckItem(m, ITEM_WIZARD, arg_wizard);
5496
5497         /* Sounds submenu */
5498         m = GetMenuHandle(SUBMENU_SOUND);
5499
5500         /* Get menu size */
5501         n = CountMItems(m);
5502
5503         /* Reset menu */
5504         for (i = 1; i <= n; i++)
5505         {
5506                 /* Reset */
5507                 DisableItem(m, i);
5508                 CheckItem(m, i, FALSE);
5509         }
5510         
5511         /* Item "Sound On/Off" */
5512         EnableItem(m, ITEM_USE_SOUND);
5513         CheckItem(m, ITEM_USE_SOUND, arg_sound);
5514
5515         /* Item "Sound Config" */
5516         EnableItem(m, ITEM_SOUND_SETTING);
5517
5518         /* Graphics submenu */
5519         m = GetMenuHandle(SUBMENU_GRAPH);
5520
5521         /* Get menu size */
5522         n = CountMItems(m);
5523
5524         /* Reset menu */
5525         for (i = 1; i <= n; i++)
5526         {
5527                 /* Reset */
5528                 DisableItem(m, i);
5529                 CheckItem(m, i, FALSE);
5530         }
5531         
5532         /* Item "None" */
5533         EnableItem(m, ITEM_NONE);
5534         CheckItem(m, ITEM_NONE, (graf_mode == GRAF_MODE_NONE));
5535
5536         /* Item "8x8" */
5537         EnableItem(m, ITEM_8X8);
5538         CheckItem(m, ITEM_8X8, (graf_mode == GRAF_MODE_8X8));
5539
5540         /* Item "16x16" */
5541         EnableItem(m, ITEM_16X16);
5542         CheckItem(m, ITEM_16X16, (graf_mode == GRAF_MODE_16X16));
5543
5544         /* Item "Bigtile" */
5545         EnableItem(m, ITEM_BIGTILE);
5546         CheckItem(m, ITEM_BIGTILE, arg_bigtile);
5547
5548
5549         /* TIleWidth submenu */
5550         m = GetMenuHandle(SUBMENU_TILEWIDTH);
5551
5552         /* Get menu size */
5553         n = CountMItems(m);
5554
5555         /* Reset menu */
5556         for (i = 1; i <= n; i++)
5557         {
5558                 /* Reset */
5559                 DisableItem(m, i);
5560                 CheckItem(m, i, FALSE);
5561         }
5562
5563         /* Active window */
5564         if (td)
5565         {
5566                 /* Analyze sizes */
5567                 for (i = 1; i <= n; i++)
5568                 {
5569                         /* Analyze size */
5570                         /* GetMenuItemText(m,i,s); */
5571                         GetMenuItemText(m, i, s);
5572                         s[s[0]+1] = '\0';
5573                         value = atoi((char*)(s+1));
5574
5575                         /* Enable */
5576                         if (value >= td->font_wid) EnableItem(m, i);
5577
5578                         /* Check the current size */
5579                         if (td->tile_wid == value) CheckItem(m, i, TRUE);
5580                 }
5581         }
5582
5583
5584         /* TileHeight submenu */
5585         m = GetMenuHandle(SUBMENU_TILEHEIGHT);
5586
5587         /* Get menu size */
5588         n = CountMItems(m);
5589
5590         /* Reset menu */
5591         for (i = 1; i <= n; i++)
5592         {
5593                 /* Reset */
5594                 DisableItem(m, i);
5595                 CheckItem(m, i, FALSE);
5596         }
5597
5598         /* Active window */
5599         if (td)
5600         {
5601                 /* Analyze sizes */
5602                 for (i = 1; i <= n; i++)
5603                 {
5604                         /* Analyze size */
5605                         GetMenuItemText(m, i, s);
5606                         s[s[0]+1] = '\0';
5607                         value = atoi((char*)(s+1));
5608
5609                         /* Enable */
5610                         if (value >= td->font_hgt) EnableItem(m, i);
5611
5612                         /* Check the current size */
5613                         if (td->tile_hgt == value) CheckItem(m, i, TRUE);
5614                 }
5615         }
5616 #endif
5617
5618 }
5619
5620
5621 /*
5622  * Process a menu selection (see above)
5623  *
5624  * Hack -- assume that invalid menu selections are disabled above,
5625  * which I have been informed may not be reliable.  XXX XXX XXX
5626  */
5627 static void menu(long mc)
5628 {
5629         int i;
5630
5631         int menuid, selection;
5632
5633         static unsigned char s[1000];
5634
5635         short fid;
5636
5637         term_data *td = NULL;
5638
5639         WindowPtr old_win;
5640
5641
5642         /* Analyze the menu command */
5643         menuid = HiWord(mc);
5644         selection = LoWord(mc);
5645
5646
5647         /* Find the window */
5648         for (i = 0; i < MAX_TERM_DATA; i++)
5649         {
5650                 /* Skip dead windows */
5651                 if (!data[i].t) continue;
5652
5653                 /* Notice matches */
5654                 if (data[i].w == FrontWindow()) td = &data[i];
5655         }
5656
5657
5658         /* Branch on the menu */
5659         switch (menuid)
5660         {
5661                 /* Apple Menu */
5662                 case MENU_APPLE:
5663                 {
5664                         /* About Angband... */
5665 #if TARGET_API_MAC_CARBON
5666                         if (selection == ITEM_ABOUT)
5667                         {
5668                                 DialogPtr dialog;
5669                                 short item_hit;
5670
5671                                 /* Get the about dialogue */
5672                                 dialog=GetNewDialog(128, 0, (WindowPtr)-1);
5673
5674                                 /* Move it to the middle of the screen */
5675                                 RepositionWindow(
5676                                         GetDialogWindow(dialog),
5677                                         NULL,
5678                                         kWindowCenterOnMainScreen);
5679
5680                                 /* Show the dialog */
5681                                 TransitionWindow(GetDialogWindow(dialog),
5682                                         kWindowZoomTransitionEffect,
5683                                         kWindowShowTransitionAction,
5684                                         NULL);
5685
5686                                 /* Wait for user to click on it */
5687                                 ModalDialog(0, &item_hit);
5688
5689                                 /* Free the dialogue */
5690                                 DisposeDialog(dialog);
5691                                 break;
5692                         }
5693 #else
5694                         if (selection == ITEM_ABOUT)
5695                         {
5696                                 DialogPtr dialog;
5697                                 Rect r;
5698                                 short item_hit;
5699
5700                                 dialog=GetNewDialog(128, 0, (WindowPtr)-1);
5701
5702                                 r=dialog->portRect;
5703                                 center_rect(&r, &qd.screenBits.bounds);
5704                                 MoveWindow(dialog, r.left, r.top, 1);
5705                                 ShowWindow(dialog);
5706                                 ModalDialog(0, &item_hit);
5707                                 DisposeDialog(dialog);
5708                                 break;
5709                         }
5710
5711                         /* Desk accessory */
5712                         GetMenuItemText(GetMenuHandle(MENU_APPLE), selection, s);
5713                         OpenDeskAcc(s);
5714                         break;
5715 #endif
5716                 }
5717
5718                 /* File Menu */
5719                 case MENU_FILE:
5720                 {
5721                         switch (selection)
5722                         {
5723                                 /* New */
5724                                 case ITEM_NEW:
5725                                 {
5726                                         do_menu_file_new();
5727                                         break;
5728                                 }
5729
5730                                 /* Open... */
5731                                 case ITEM_OPEN:
5732                                 {
5733                                         do_menu_file_open(FALSE);
5734                                         break;
5735                                 }
5736
5737                                 /* Import... */
5738                                 case ITEM_IMPORT:
5739                                 {
5740                                         do_menu_file_open(TRUE);
5741                                         break;
5742                                 }
5743
5744                                 /* Close */
5745                                 case ITEM_CLOSE:
5746                                 {
5747                                         /* No window */
5748                                         if (!td) break;
5749
5750                                         /* Not Mapped */
5751                                         td->mapped = FALSE;
5752
5753                                         /* Not Mapped */
5754                                         td->t->mapped_flag = FALSE;
5755
5756                                         /* Hide the window */
5757                                         HideWindow(td->w);
5758
5759                                         break;
5760                                 }
5761
5762                                 /* Save */
5763                                 case ITEM_SAVE:
5764                                 {
5765                                         if (!can_save){
5766 #ifdef JP
5767                                                 plog("º£¤Ï¥»¡¼¥Ö¤¹¤ë¤³¤È¤Ï½ÐÍè¤Þ¤»¤ó¡£");
5768 #else
5769                                                 plog("You may not do that right now.");
5770 #endif
5771                                                 break;
5772                                         }
5773                                         
5774                                         /* Hack -- Forget messages */
5775                                         msg_flag = FALSE;
5776
5777                                         /* Hack -- Save the game */
5778                                         do_cmd_save_game(FALSE);
5779
5780                                         break;
5781                                 }
5782
5783                                 /* Quit (with save) */
5784                                 case ITEM_QUIT:
5785                                 {
5786                                         /* Save the game (if necessary) */
5787                                         if (game_in_progress && character_generated)
5788                                         {
5789                                                 if (!can_save){
5790 #ifdef JP
5791                                                         plog("º£¤Ï¥»¡¼¥Ö¤¹¤ë¤³¤È¤Ï½ÐÍè¤Þ¤»¤ó¡£");
5792 #else
5793                                                         plog("You may not do that right now.");
5794 #endif
5795                                                         break;
5796                                                 }
5797                                                 /* Hack -- Forget messages */
5798                                                 msg_flag = FALSE;
5799
5800                                                 /* Save the game */
5801 #if 0
5802                                                 do_cmd_save_game(FALSE);
5803 #endif
5804                                                 Term_key_push(SPECIAL_KEY_QUIT);
5805                                                 break;
5806                                         }
5807
5808                                         /* Quit */
5809                                         quit(NULL);
5810                                         break;
5811                                 }
5812                         }
5813                         break;
5814                 }
5815
5816                 /* Edit menu */
5817                 case MENU_EDIT:
5818                 {
5819                         /* Unused */
5820                         break;
5821                 }
5822
5823                 /* Font menu */
5824                 case MENU_FONT:
5825                 {
5826                         /* Require a window */
5827                         if (!td) break;
5828
5829                         /* Memorize old */
5830                         old_win = active;
5831
5832                         /* Activate */
5833                         activate(td->w);
5834
5835                         /* Toggle the "bold" setting */
5836                         if (selection == ITEM_BOLD)
5837                         {
5838                                 /* Toggle the setting */
5839                                 if (td->font_face & bold)
5840                                 {
5841                                         td->font_face &= ~bold;
5842                                 }
5843                                 else
5844                                 {
5845                                         td->font_face |= bold;
5846                                 }
5847
5848                                 /* Tile Width Hight Init */
5849                                 td->tile_wid = td->tile_hgt = 0;
5850
5851                                 /* Apply and Verify */
5852                                 term_data_check_font(td);
5853                                 term_data_check_size(td);
5854
5855                                 /* Resize and Redraw */
5856                                 term_data_resize(td);
5857                                 term_data_redraw(td);
5858
5859                                 break;
5860                         }
5861
5862                         /* Toggle the "wide" setting */
5863                         if (selection == ITEM_WIDE)
5864                         {
5865                                 /* Toggle the setting */
5866                                 if (td->font_face & extend)
5867                                 {
5868                                         td->font_face &= ~extend;
5869                                 }
5870                                 else
5871                                 {
5872                                         td->font_face |= extend;
5873                                 }
5874
5875                                 /* Tile Width Hight Init */
5876                                 td->tile_wid = td->tile_hgt = 0;
5877
5878                                 /* Apply and Verify */
5879                                 term_data_check_font(td);
5880                                 term_data_check_size(td);
5881
5882                                 /* Resize and Redraw */
5883                                 term_data_resize(td);
5884                                 term_data_redraw(td);
5885
5886                                 break;
5887                         }
5888
5889                         /* Get a new font name */
5890                         GetMenuItemText(GetMenuHandle(MENU_FONT), selection, s);
5891                         GetFNum(s, &fid);
5892
5893                         /* Save the new font id */
5894                         td->font_id = fid;
5895
5896                         /* Current size is bad for new font */
5897                         if (!RealFont(td->font_id, td->font_size))
5898                         {
5899                                 /* Find similar size */
5900                                 for (i = 1; i <= 32; i++)
5901                                 {
5902                                         /* Adjust smaller */
5903                                         if (td->font_size - i >= 8)
5904                                         {
5905                                                 if (RealFont(td->font_id, td->font_size - i))
5906                                                 {
5907                                                         td->font_size -= i;
5908                                                         break;
5909                                                 }
5910                                         }
5911
5912                                         /* Adjust larger */
5913                                         if (td->font_size + i <= 128)
5914                                         {
5915                                                 if (RealFont(td->font_id, td->font_size + i))
5916                                                 {
5917                                                         td->font_size += i;
5918                                                         break;
5919                                                 }
5920                                         }
5921                                 }
5922                         }
5923
5924                         /* Tile Width Hight Init */
5925                         td->tile_wid = td->tile_hgt = 0;
5926
5927                         /* Apply and Verify */
5928                         term_data_check_font(td);
5929                         term_data_check_size(td);
5930
5931                         /* Resize and Redraw */
5932                         term_data_resize(td);
5933                         term_data_redraw(td);
5934
5935                         /* Restore the window */
5936                         activate(old_win);
5937
5938                         break;
5939                 }
5940
5941                 /* Size menu */
5942                 case MENU_SIZE:
5943                 {
5944                         if (!td) break;
5945
5946                         /* Save old */
5947                         old_win = active;
5948
5949                         /* Activate */
5950                         activate(td->w);
5951
5952                         GetMenuItemText(GetMenuHandle(MENU_SIZE), selection, s);
5953                         s[s[0]+1]=0;
5954                         td->font_size = atoi((char*)(s+1));
5955
5956                         /* Tile Width Hight Init */
5957                         td->tile_wid = td->tile_hgt = 0;
5958
5959                         /* Apply and Verify */
5960                         term_data_check_font(td);
5961                         term_data_check_size(td);
5962
5963                         /* Resize and Redraw */
5964                         term_data_resize(td);
5965                         term_data_redraw(td);
5966
5967                         /* Restore */
5968                         activate(old_win);
5969
5970                         break;
5971                 }
5972
5973                 /* Window menu */
5974                 case MENU_WINDOWS:
5975                 {
5976                         /* Parse */
5977                         i = selection - 1;
5978
5979                         /* Check legality of choice */
5980                         if ((i < 0) || (i >= MAX_TERM_DATA)) break;
5981
5982                         /* Obtain the window */
5983                         td = &data[i];
5984
5985                         /* Mapped */
5986                         td->mapped = TRUE;
5987
5988                         /* Link */      
5989                         term_data_link(i);
5990
5991                         /* Mapped (?) */
5992                         td->t->mapped_flag = TRUE;
5993
5994                         /* Show the window */
5995                         ShowWindow(td->w);
5996
5997                         /* Bring to the front */
5998                         SelectWindow(td->w);
5999
6000                         break;
6001                 }
6002
6003                 /* Special menu */
6004                 case MENU_SPECIAL:
6005                 {
6006                         switch (selection)
6007                         {
6008                                 case ITEM_FIDDLE:
6009                                 {
6010                                         arg_fiddle = !arg_fiddle;
6011                                         break;
6012                                 }
6013
6014                                 case ITEM_WIZARD:
6015                                 {
6016                                         arg_wizard = !arg_wizard;
6017                                         break;
6018                                 }
6019                         }
6020
6021                         break;
6022                 }
6023
6024                 /* Sounds submenu */
6025                 case SUBMENU_SOUND:
6026                 {
6027                         switch (selection)
6028                         {
6029                                 case ITEM_USE_SOUND:
6030                                 {
6031                                         /* Toggle arg_sound */
6032                                         arg_sound = !arg_sound;
6033
6034                                         /* React to changes */
6035                                         Term_xtra(TERM_XTRA_REACT, 0);
6036
6037                                         break;
6038                                 }
6039
6040                                 case ITEM_SOUND_SETTING:
6041                                 {
6042                                         SoundConfigDLog();
6043
6044                                         break;
6045                                 }
6046                         }
6047
6048                         break;
6049                 }
6050
6051                 /* Graphics submenu */
6052                 case SUBMENU_GRAPH:
6053                 {
6054                         switch (selection)
6055                         {
6056                                 case ITEM_NONE:
6057                                 {
6058                                         graf_mode_req = GRAF_MODE_NONE;
6059
6060                                         break;
6061                                 }
6062
6063                                 case ITEM_8X8:
6064                                 {
6065                                         graf_mode_req = GRAF_MODE_8X8;
6066
6067                                         break;
6068                                 }
6069
6070                                 case ITEM_16X16:
6071                                 {
6072                                         graf_mode_req = GRAF_MODE_16X16;
6073
6074                                         break;
6075                                 }
6076
6077                                 case ITEM_BIGTILE:
6078                                 {
6079                                         term *old = Term;
6080                                         term_data *td = &data[0];
6081
6082                                         /* Toggle "arg_bigtile" */
6083                                         arg_bigtile = !arg_bigtile;
6084
6085                                         /* Activate */
6086                                         Term_activate(td->t);
6087
6088                                         /* Resize the term */
6089                                         Term_resize(td->cols, td->rows);
6090
6091                                         /* Activate old */
6092                                         Term_activate(old);
6093
6094                                         break;
6095                                 }
6096                         }
6097
6098                         /* Hack -- Force redraw */
6099                         Term_key_push(KTRL('R'));
6100
6101                         break;
6102                 }
6103
6104                 /* TileWidth submenu */
6105                 case SUBMENU_TILEWIDTH:
6106                 {
6107                         if (!td) break;
6108
6109                         /* Save old */
6110                         old_win = active;
6111
6112                         /* Activate */
6113                         activate(td->w);
6114
6115                         /* Analyse value */
6116                         GetMenuItemText(GetMenuHandle(SUBMENU_TILEWIDTH), selection, s);
6117                         s[s[0]+1]=0;
6118                         td->tile_wid = atoi((char*)(s+1));
6119
6120                         /* Apply and Verify */
6121                         term_data_check_size(td);
6122
6123                         /* Resize and Redraw */
6124                         term_data_resize(td);
6125                         term_data_redraw(td);
6126
6127                         /* Restore */
6128                         activate(old_win);
6129
6130                         break;
6131                 }
6132
6133                 /* TileHeight submenu */
6134                 case SUBMENU_TILEHEIGHT:
6135                 {
6136                         if (!td) break;
6137
6138                         /* Save old */
6139                         old_win = active;
6140
6141                         /* Activate */
6142                         activate(td->w);
6143
6144                         /* Analyse value */
6145                         GetMenuItemText(GetMenuHandle(SUBMENU_TILEHEIGHT), selection, s);
6146                         s[s[0]+1]=0;
6147                         td->tile_hgt = atoi((char*)(s+1));
6148
6149                         /* Apply and Verify */
6150                         term_data_check_size(td);
6151
6152                         /* Resize and Redraw */
6153                         term_data_resize(td);
6154                         term_data_redraw(td);
6155
6156                         /* Restore */
6157                         activate(old_win);
6158
6159                         break;
6160                 }
6161         }
6162
6163
6164         /* Clean the menu */
6165         HiliteMenu(0);
6166 }
6167
6168
6169 #ifdef USE_SFL_CODE
6170
6171
6172 /*
6173  * Check for extra required parameters -- From "Maarten Hazewinkel"
6174  */
6175 static OSErr CheckRequiredAEParams(const AppleEvent *theAppleEvent)
6176 {
6177         OSErr   aeError;
6178         DescType        returnedType;
6179         Size    actualSize;
6180
6181         aeError = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard,
6182                                     &returnedType, NULL, 0, &actualSize);
6183
6184         if (aeError == errAEDescNotFound) return (noErr);
6185
6186         if (aeError == noErr) return (errAEParamMissed);
6187
6188         return (aeError);
6189 }
6190
6191
6192 /*
6193  * Apple Event Handler -- Open Application
6194  */
6195 static pascal OSErr AEH_Start(const AppleEvent *theAppleEvent,
6196                               AppleEvent *reply, long handlerRefCon)
6197 {
6198 #pragma unused(reply, handlerRefCon)
6199
6200         return (CheckRequiredAEParams(theAppleEvent));
6201 }
6202
6203
6204 /*
6205  * Apple Event Handler -- Quit Application
6206  */
6207 static pascal OSErr AEH_Quit(const AppleEvent *theAppleEvent,
6208                              AppleEvent *reply, long handlerRefCon)
6209 {
6210 #pragma unused(reply, handlerRefCon)
6211 #if TARGET_API_MAC_CARBON
6212 #pragma unused(theAppleEvent)
6213
6214         /* Save the game (if necessary) */
6215         if (game_in_progress && character_generated)
6216         {
6217                         if (!can_save){
6218 #ifdef JP
6219                                 plog("º£¤Ï¥»¡¼¥Ö¤¹¤ë¤³¤È¤Ï½ÐÍè¤Þ¤»¤ó¡£");
6220 #else
6221                                 plog("You may not do that right now.");
6222 #endif
6223                                 return;
6224                         }
6225                         /* Hack -- Forget messages */
6226                         msg_flag = FALSE;
6227
6228                         /* Save the game */
6229 #if 0
6230                         do_cmd_save_game(FALSE);
6231 #endif
6232                         Term_key_push(SPECIAL_KEY_QUIT);
6233                         return;
6234                 }
6235
6236                 /* Quit */
6237                 quit(NULL);
6238 #else
6239         /* Quit later */
6240         quit_when_ready = TRUE;
6241
6242         /* Check arguments */
6243         return (CheckRequiredAEParams(theAppleEvent));
6244 #endif
6245 }
6246
6247
6248 /*
6249  * Apple Event Handler -- Print Documents
6250  */
6251 static pascal OSErr AEH_Print(const AppleEvent *theAppleEvent,
6252                               AppleEvent *reply, long handlerRefCon)
6253 {
6254 #pragma unused(theAppleEvent, reply, handlerRefCon)
6255
6256         return (errAEEventNotHandled);
6257 }
6258
6259
6260 /*
6261  * Apple Event Handler by Steve Linberg (slinberg@crocker.com).
6262  *
6263  * The old method of opening savefiles from the finder does not work
6264  * on the Power Macintosh, because CountAppFiles and GetAppFiles,
6265  * used to return information about the selected document files when
6266  * an application is launched, are part of the Segment Loader, which
6267  * is not present in the RISC OS due to the new memory architecture.
6268  *
6269  * The "correct" way to do this is with AppleEvents.  The following
6270  * code is modeled on the "Getting Files Selected from the Finder"
6271  * snippet from Think Reference 2.0.  (The prior sentence could read
6272  * "shamelessly swiped & hacked")
6273  */
6274 static pascal OSErr AEH_Open(const AppleEvent *theAppleEvent,
6275                              AppleEvent* reply, long handlerRefCon)
6276 {
6277 #pragma unused(reply, handlerRefCon)
6278
6279         FSSpec          myFSS;
6280         AEDescList      docList;
6281         OSErr           err;
6282         Size            actualSize;
6283         AEKeyword       keywd;
6284         DescType        returnedType;
6285         char            foo[128];
6286         FInfo           myFileInfo;
6287
6288         /* Put the direct parameter (a descriptor list) into a docList */
6289         err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &docList);
6290         if (err) return err;
6291
6292         /*
6293          * We ignore the validity check, because we trust the FInder, and we only
6294          * allow one savefile to be opened, so we ignore the depth of the list.
6295          */
6296
6297         err = AEGetNthPtr(&docList, 1L, typeFSS, &keywd,
6298                           &returnedType, (Ptr) &myFSS, sizeof(myFSS), &actualSize);
6299         if (err) return err;
6300
6301         /* Only needed to check savefile type below */
6302         err = FSpGetFInfo(&myFSS, &myFileInfo);
6303         if (err)
6304         {
6305                 sprintf(foo, "Arg!  FSpGetFInfo failed with code %d", err);
6306                 mac_warning (foo);
6307                 return err;
6308         }
6309
6310         /* Ignore non 'SAVE' files */
6311         if (myFileInfo.fdType != 'SAVE') return noErr;
6312
6313 #ifdef MACH_O_CARBON
6314
6315         /* Extract a file name */
6316         (void)spec_to_path(&myFSS, savefile, sizeof(savefile));
6317
6318 #else
6319
6320         /* XXX XXX XXX Extract a file name */
6321         PathNameFromDirID(myFSS.parID, myFSS.vRefNum, (StringPtr)savefile);
6322         pstrcat((StringPtr)savefile, (StringPtr)&myFSS.name);
6323
6324         /* Convert the string */
6325         ptocstr((StringPtr)savefile);
6326
6327 #endif /* MACH_O_CARBON */
6328
6329         /* Delay actual open */
6330         open_when_ready = TRUE;
6331
6332         /* Dispose */
6333         err = AEDisposeDesc(&docList);
6334
6335         /* Success */
6336         return noErr;
6337 }
6338
6339
6340 #endif
6341
6342
6343
6344 /*
6345  * Macintosh modifiers (event.modifier & ccc):
6346  *   cmdKey, optionKey, shiftKey, alphaLock, controlKey
6347  *
6348  *
6349  * Macintosh Keycodes (0-63 normal, 64-95 keypad, 96-127 extra):
6350  *
6351  * Return:36
6352  * Delete:51
6353  *
6354  * Period:65
6355  * Star:67
6356  * Plus:69
6357  * Clear:71
6358  * Slash:75
6359  * Enter:76
6360  * Minus:78
6361  * Equal:81
6362  * 0-7:82-89
6363  * 8-9:91-92
6364  *
6365  * F5: 96
6366  * F6: 97
6367  * F7: 98
6368  * F3:99
6369  * F8:100
6370  * F10:109
6371  * F11:103
6372  * F13:105
6373  * F14:107
6374  * F9:101
6375  * F12:111
6376  * F15:113
6377  * Help:114
6378  * Home:115
6379  * PgUp:116
6380  * Del:117
6381  * F4: 118
6382  * End:119
6383  * F2:120
6384  * PgDn:121
6385  * F1:122
6386  * Lt:123
6387  * Rt:124
6388  * Dn:125
6389  * Up:126
6390  */
6391
6392
6393 /*
6394  * Optimize non-blocking calls to "CheckEvents()"
6395  * Idea from "Maarten Hazewinkel <mmhazewi@cs.ruu.nl>"
6396  */
6397 #define EVENT_TICKS 6
6398
6399
6400 /*
6401  * Check for Events, return TRUE if we process any
6402  *
6403  * Hack -- Handle AppleEvents if appropriate (ignore result code).
6404  */
6405 static bool CheckEvents(bool wait)
6406 {
6407         EventRecord event;
6408
6409         WindowPtr w;
6410
6411         Rect r;
6412
6413         long newsize;
6414
6415         int ch, ck;
6416
6417         int mc, ms, mo, mx;
6418
6419         int i;
6420
6421         term_data *td = NULL;
6422
6423         huge curTicks;
6424
6425         static huge lastTicks = 0L;
6426
6427
6428         /* Access the clock */
6429         curTicks = TickCount();
6430
6431         /* Hack -- Allow efficient checking for non-pending events */
6432         if (!wait && (curTicks < lastTicks + EVENT_TICKS)) return (FALSE);
6433
6434         /* Timestamp last check */
6435         lastTicks = curTicks;
6436
6437 #if TARGET_API_MAC_CARBON
6438         WaitNextEvent( everyEvent, &event, 1L, nil );
6439 #else
6440         /* Let the "system" run */
6441         SystemTask();
6442
6443         /* Get an event (or null) */
6444         GetNextEvent(everyEvent, &event);
6445 #endif
6446
6447         /* Hack -- Nothing is ready yet */
6448         if (event.what == nullEvent) return (FALSE);
6449
6450         /* Analyze the event */
6451         switch (event.what)
6452         {
6453
6454 #if 0
6455
6456                 case activateEvt:
6457                 {
6458                         w = (WindowPtr)event.message;
6459
6460                         activate(w);
6461
6462                         break;
6463                 }
6464
6465 #endif
6466
6467                 case updateEvt:
6468                 {
6469                         /* Extract the window */
6470                         w = (WindowPtr)event.message;
6471
6472                         /* Find the window */
6473                         for (i = 0; i < MAX_TERM_DATA; i++)
6474                         {
6475                                 /* Skip dead windows */
6476                                 if (!data[i].t) continue;
6477
6478                                 /* Notice matches */
6479                                 if (data[i].w == w) td = &data[i];
6480                         }
6481
6482                         /* Hack XXX XXX XXX */
6483                         BeginUpdate(w);
6484                         EndUpdate(w);
6485
6486                         /* Redraw the window */
6487                         if (td) term_data_redraw(td);
6488
6489                         break;
6490                 }
6491
6492                 case keyDown:
6493                 case autoKey:
6494                 {
6495                         /* Extract some modifiers */
6496                         mc = (event.modifiers & controlKey) ? TRUE : FALSE;
6497                         ms = (event.modifiers & shiftKey) ? TRUE : FALSE;
6498                         mo = (event.modifiers & optionKey) ? TRUE : FALSE;
6499                         mx = (event.modifiers & cmdKey) ? TRUE : FALSE;
6500
6501                         /* Keypress: (only "valid" if ck < 96) */
6502                         ch = (event.message & charCodeMask) & 255;
6503
6504                         /* Keycode: see table above */
6505                         ck = ((event.message & keyCodeMask) >> 8) & 255;
6506
6507                         /* Command + "normal key" -> menu action */
6508                         if (mx && (ck < 64))
6509                         {
6510                                 /* Hack -- Prepare the menus */
6511                                 setup_menus();
6512
6513                                 /* Run the Menu-Handler */
6514                                 menu(MenuKey(ch));
6515
6516                                 /* Turn off the menus */
6517                                 HiliteMenu(0);
6518
6519                                 /* Done */
6520                                 break;
6521                         }
6522
6523
6524                         /* Hide the mouse pointer */
6525                         ObscureCursor();
6526
6527                         /* Normal key -> simple keypress */
6528                         if (ck < 64)
6529                         {
6530                                 /* Enqueue the keypress */
6531                                 Term_keypress(ch);
6532                         }
6533
6534                         /* Bizarre key -> encoded keypress */
6535                         else if (ck <= 127)
6536                         {
6537                                 /* Hack -- introduce with control-underscore */
6538                                 Term_keypress(31);
6539
6540                                 /* Send some modifier keys */
6541                                 if (mc) Term_keypress('C');
6542                                 if (ms) Term_keypress('S');
6543                                 if (mo) Term_keypress('O');
6544                                 if (mx) Term_keypress('X');
6545
6546                                 /* Hack -- Downshift and encode the keycode */
6547                                 Term_keypress('0' + (ck - 64) / 10);
6548                                 Term_keypress('0' + (ck - 64) % 10);
6549
6550                                 /* Hack -- Terminate the sequence */
6551                                 /* MPW can generate 10 or 13 for keycode of '\r' */
6552                                 /* -noMapCR option swaps '\r' and '\n' */
6553                                 Term_keypress('\r');
6554                         }
6555
6556                         break;
6557                 }
6558
6559                 case mouseDown:
6560                 {
6561                         int code;
6562
6563                         /* Analyze click location */
6564                         code = FindWindow(event.where, &w);
6565
6566                         /* Find the window */
6567                         for (i = 0; i < MAX_TERM_DATA; i++)
6568                         {
6569                                 /* Skip dead windows */
6570                                 if (!data[i].t) continue;
6571
6572                                 /* Notice matches */
6573                                 if (data[i].w == w) td = &data[i];
6574                         }
6575
6576                         /* Analyze */
6577                         switch (code)
6578                         {
6579                                 case inMenuBar:
6580                                 {
6581                                         setup_menus();
6582                                         menu(MenuSelect(event.where));
6583                                         HiliteMenu(0);
6584                                         break;
6585                                 }
6586 #if !TARGET_API_MAC_CARBON
6587                                 case inSysWindow:
6588                                 {
6589                                         SystemClick(&event, w);
6590                                         break;
6591                                 }
6592 #endif
6593
6594                                 case inDrag:
6595                                 {
6596                                         Point p;
6597
6598                                         WindowPtr old_win;
6599                                         BitMap screen;
6600                                         Rect portRect;
6601 #if TARGET_API_MAC_CARBON                                               
6602                                         GetQDGlobalsScreenBits( &screen );
6603 #else
6604                                         screen = qd.screenBits;
6605 #endif  
6606                                         r = screen.bounds;
6607                                         r.top += 20; /* GetMBarHeight() XXX XXX XXX */
6608                                         InsetRect(&r, 4, 4);
6609                                         DragWindow(w, event.where, &r);
6610
6611                                         /* Oops */
6612                                         if (!td) break;
6613
6614                                         /* Save */
6615                                         old_win = active;
6616
6617                                         /* Activate */
6618                                         activate(td->w);
6619
6620                                         /* Analyze */
6621 #if TARGET_API_MAC_CARBON
6622                                         GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &portRect );
6623 #else
6624                                         portRect = td->w->portRect;
6625                                         local_to_global( &portRect );
6626 #endif
6627                                         p.h = portRect.left;
6628                                         p.v = portRect.top;
6629 #if !TARGET_API_MAC_CARBON
6630                                         LocalToGlobal(&p);
6631 #endif
6632                                         td->r.left = p.h;
6633                                         td->r.top = p.v;
6634
6635                                         /* Restore */
6636                                         activate(old_win);
6637
6638                                         /* Apply and Verify */
6639                                         term_data_check_size(td);
6640
6641                                         break;
6642                                 }
6643
6644                                 case inGoAway:
6645                                 {
6646                                         /* Oops */
6647                                         if (!td) break;
6648
6649                                         /* Track the go-away box */
6650                                         if (TrackGoAway(w, event.where))
6651                                         {
6652                                                 /* Not Mapped */
6653                                                 td->mapped = FALSE;
6654
6655                                                 /* Not Mapped */
6656                                                 td->t->mapped_flag = FALSE;
6657
6658                                                 /* Hide the window */
6659                                                 HideWindow(td->w);
6660                                         }
6661
6662                                         break;
6663                                 }
6664
6665                                 case inGrow:
6666                                 {
6667                                         s16b x, y;
6668
6669                                         term *old = Term;
6670                                         BitMap          screen;
6671         
6672 #if TARGET_API_MAC_CARBON
6673                                         GetQDGlobalsScreenBits( &screen );
6674 #else
6675                                         screen = qd.screenBits;
6676 #endif
6677                                         /* Oops */
6678                                         if (!td) break;
6679
6680                                         /* Fake rectangle */
6681                                         r.left = 20 * td->tile_wid + td->size_ow1;
6682                                         r.right = screen.bounds.right;
6683                                         r.top = 1 * td->tile_hgt + td->size_oh1;
6684                                         r.bottom = screen.bounds.bottom;
6685
6686                                         /* Grow the rectangle */
6687                                         newsize = GrowWindow(w, event.where, &r);
6688
6689                                         /* Handle abort */
6690                                         if (!newsize) break;
6691
6692                                         /* Extract the new size in pixels */
6693                                         y = HiWord(newsize) - td->size_oh1 - td->size_oh2;
6694                                         x = LoWord(newsize) - td->size_ow1 - td->size_ow2;
6695
6696                                         /* Extract a "close" approximation */
6697                                         td->rows = y / td->tile_hgt;
6698                                         td->cols = x / td->tile_wid;
6699
6700                                         /* Apply and Verify */
6701                                         term_data_check_size(td);
6702                                         /* Activate */
6703                                         Term_activate(td->t);
6704
6705                                         /* Hack -- Resize the term */
6706                                         Term_resize(td->cols, td->rows);
6707
6708                                         /* Resize and Redraw */
6709                                         term_data_resize(td);
6710                                         term_data_redraw(td);
6711
6712                                         /* Restore */
6713                                         Term_activate(old);
6714
6715                                         break;
6716                                 }
6717
6718                                 case inContent:
6719                                 {
6720                                         SelectWindow(w);
6721
6722                                         break;
6723                                 }
6724                         }
6725
6726                         break;
6727                 }
6728
6729                 /* Disk Event -- From "Maarten Hazewinkel" */
6730                 case diskEvt:
6731                 {
6732
6733 #if TARGET_API_MAC_CARBON
6734 #else
6735                         /* check for error when mounting the disk */
6736                         if (HiWord(event.message) != noErr)
6737                         {
6738                                 Point p =
6739                                 {120, 120};
6740
6741                                 DILoad();
6742                                 DIBadMount(p, event.message);
6743                                 DIUnload();
6744                         }
6745 #endif
6746                         break;
6747                 }
6748
6749                 /* OS Event -- From "Maarten Hazewinkel" */
6750                 case osEvt:
6751                 {
6752                         switch ((event.message >> 24) & 0x000000FF)
6753                         {
6754                                 case suspendResumeMessage:
6755
6756                                 /* Resuming: activate the front window */
6757                                 if (event.message & resumeFlag)
6758                                 {
6759 #if TARGET_API_MAC_CARBON
6760                                         Cursor  arrow;
6761                                                 
6762                                         SetPortWindowPort( FrontWindow() );
6763                                         
6764                                         GetQDGlobalsArrow( &arrow );
6765                                         SetCursor(&arrow);
6766 #else
6767                                         SetPort(FrontWindow());
6768                                         SetCursor(&qd.arrow);
6769 #endif
6770                                 }
6771
6772                                 /* Suspend: deactivate the front window */
6773                                 else
6774                                 {
6775                                         /* Nothing */
6776                                 }
6777
6778                                 break;
6779                         }
6780
6781                         break;
6782                 }
6783
6784 #ifdef USE_SFL_CODE
6785
6786                 /* From "Steve Linberg" and "Maarten Hazewinkel" */
6787                 case kHighLevelEvent:
6788                 {
6789 #if TARGET_API_MAC_CARBON
6790                         AEProcessAppleEvent(&event);
6791 #else
6792                         /* Process apple events */
6793                         if (AEProcessAppleEvent(&event) != noErr)
6794                         {
6795                                 #ifdef JP
6796                                 plog("Apple Event Handler¤Î¥¨¥é¡¼¤Ç¤¹.");
6797                                 #else
6798                                 plog("Error in Apple Event Handler!");
6799                                 #endif
6800                         }
6801
6802                         /* Handle "quit_when_ready" */
6803                         if (quit_when_ready)
6804                         {
6805                                 /* Forget */
6806                                 quit_when_ready = FALSE;
6807
6808                                 /* Do the menu key */
6809                                 menu(MenuKey('q'));
6810
6811                                 /* Turn off the menus */
6812                                 HiliteMenu(0);
6813                         }
6814
6815                         /* Handle "open_when_ready" */
6816                         handle_open_when_ready();
6817 #endif
6818
6819                         break;
6820                 }
6821
6822 #endif
6823
6824         }
6825
6826
6827         /* Something happened */
6828         return (TRUE);
6829 }
6830
6831
6832
6833
6834 /*** Some Hooks for various routines ***/
6835
6836
6837 /*
6838  * Mega-Hack -- emergency lifeboat
6839  */
6840 static vptr lifeboat = NULL;
6841
6842
6843 /*
6844  * Hook to "release" memory
6845  */
6846 static vptr hook_rnfree(vptr v, huge size)
6847 {
6848
6849 #pragma unused (size)
6850
6851 #ifdef USE_MALLOC
6852
6853         /* Alternative method */
6854         free(v);
6855
6856 #else
6857
6858         /* Dispose */
6859         DisposePtr(v);
6860
6861 #endif
6862
6863         /* Success */
6864         return (NULL);
6865 }
6866
6867 /*
6868  * Hook to "allocate" memory
6869  */
6870 static vptr hook_ralloc(huge size)
6871 {
6872
6873 #ifdef USE_MALLOC
6874
6875         /* Make a new pointer */
6876         return (malloc(size));
6877
6878 #else
6879
6880         /* Make a new pointer */
6881         return (NewPtr(size));
6882
6883 #endif
6884
6885 }
6886
6887 /*
6888  * Hook to handle "out of memory" errors
6889  */
6890 static vptr hook_rpanic(huge size)
6891 {
6892
6893 #pragma unused (size)
6894
6895         /* vptr mem = NULL; */
6896
6897         /* Free the lifeboat */
6898         if (lifeboat)
6899         {
6900                 /* Free the lifeboat */
6901                 DisposePtr(lifeboat);
6902
6903                 /* Forget the lifeboat */
6904                 lifeboat = NULL;
6905
6906                 /* Mega-Hack -- Warning */
6907                 #ifdef JP
6908                 mac_warning("¥á¥â¥ê¡¼¤¬Â­¤ê¤Þ¤»¤ó!\rº£¤¹¤°½ªÎ»¤·¤Æ²¼¤µ¤¤!");
6909                 #else
6910                 mac_warning("Running out of Memory!\rAbort this process now!");
6911                 #endif
6912
6913                 /* Mega-Hack -- Never leave this function */
6914                 while (TRUE) CheckEvents(TRUE);
6915         }
6916
6917         /* Mega-Hack -- Crash */
6918         return (NULL);
6919 }
6920
6921
6922 /*
6923  * Hook to tell the user something important
6924  */
6925 static void hook_plog(cptr str)
6926 {
6927         /* Warning message */
6928         mac_warning(str);
6929 }
6930
6931 /*
6932  * Hook to tell the user something, and then quit
6933  */
6934 static void hook_quit(cptr str)
6935 {
6936         /* Warning if needed */
6937         if (str) mac_warning(str);
6938
6939 #ifdef USE_ASYNC_SOUND
6940
6941         /* Clean up sound support */
6942         cleanup_sound();
6943
6944 #endif /* USE_ASYNC_SOUND */
6945
6946         /* Write a preference file */
6947         save_pref_file();
6948
6949         /* All done */
6950         ExitToShell();
6951 }
6952
6953 /*
6954  * Hook to tell the user something, and then crash
6955  */
6956 static void hook_core(cptr str)
6957 {
6958         /* XXX Use the debugger */
6959         /* DebugStr(str); */
6960
6961         /* Warning */
6962         if (str) mac_warning(str);
6963
6964         /* Warn, then save player */
6965         #ifdef JP
6966         mac_warning("Ã×̿Ū¤Ê¥¨¥é¡¼¤Ç¤¹.\r¶¯À©Åª¤Ë¥»¡¼¥Ö¤·¤Æ½ªÎ»¤·¤Þ¤¹.");
6967         #else
6968         mac_warning("Fatal error.\rI will now attempt to save and quit.");
6969         #endif
6970
6971         /* Attempt to save */
6972         #ifdef JP
6973         if (!save_player()) mac_warning("·Ù¹ð -- ¥»¡¼¥Ö¤Ë¼ºÇÔ¤·¤Þ¤·¤¿!");
6974         #else
6975         if (!save_player()) mac_warning("Warning -- save failed!");
6976         #endif
6977         
6978         /* Quit */
6979         quit(NULL);
6980 }
6981
6982
6983
6984 /*** Main program ***/
6985
6986
6987 /*
6988  * Init some stuff
6989  *
6990  * XXX XXX XXX Hack -- This function attempts to "fix" the nasty
6991  * "Macintosh Save Bug" by using "absolute" path names, since on
6992  * System 7 machines anyway, the "current working directory" often
6993  * "changes" due to background processes, invalidating any "relative"
6994  * path names.  Note that the Macintosh is limited to 255 character
6995  * path names, so be careful about deeply embedded directories...
6996  *
6997  * XXX XXX XXX Hack -- This function attempts to "fix" the nasty
6998  * "missing lib folder bug" by allowing the user to help find the
6999  * "lib" folder by hand if the "application folder" code fails...
7000  */
7001 static void init_stuff(void)
7002 {
7003         int i;
7004
7005 #if !TARGET_API_MAC_CARBON
7006         short vrefnum;
7007         long drefnum;
7008         long junk;
7009
7010         SFTypeList types;
7011         SFReply reply;
7012 #endif
7013
7014         Rect r;
7015         Point topleft;
7016
7017         char path[1024];
7018
7019         BitMap screen;
7020         Rect screenRect;
7021
7022 #if TARGET_API_MAC_CARBON
7023         OSErr err = noErr;
7024         NavDialogOptions dialogOptions;
7025         FSSpec theFolderSpec;
7026         NavReplyRecord theReply;
7027 #endif
7028         /* Fake rectangle */
7029         r.left = 0;
7030         r.top = 0;
7031         r.right = 344;
7032         r.bottom = 188;
7033
7034         /* Center it */
7035 #if TARGET_API_MAC_CARBON
7036         screenRect = GetQDGlobalsScreenBits(&screen)->bounds;
7037 #else
7038         screenRect = qd.screenBits.bounds;
7039 #endif
7040         center_rect(&r, &screenRect);
7041
7042         /* Extract corner */
7043         topleft.v = r.top;
7044         topleft.h = r.left;
7045
7046
7047         /* Default to the "lib" folder with the application */
7048 #ifdef MACH_O_CARBON
7049         if (locate_lib(path, sizeof(path)) == NULL) quit(NULL);
7050 #else
7051         refnum_to_name(path, app_dir, app_vol, (char*)("\plib:"));
7052 #endif
7053
7054
7055         /* Check until done */
7056         while (1)
7057         {
7058                 /* Prepare the paths */
7059                 init_file_paths(path);
7060
7061                 /* Build the filename */
7062 #ifdef JP
7063                 path_build(path, sizeof(path), ANGBAND_DIR_FILE, "news_j.txt");
7064 #else
7065                 path_build(path, sizeof(path), ANGBAND_DIR_FILE, "news.txt");
7066 #endif
7067
7068                 /* Attempt to open and close that file */
7069                 if (0 == fd_close(fd_open(path, O_RDONLY))) break;
7070
7071                 /* Warning */
7072 #ifdef JP
7073                 plog_fmt("'%s' ¥Õ¥¡¥¤¥ë¤ò¥ª¡¼¥×¥ó½ÐÍè¤Þ¤»¤ó.", path);
7074 #else
7075                 plog_fmt("Unable to open the '%s' file.", path);
7076 #endif
7077
7078                 /* Warning */
7079 #ifdef JP
7080                 plog("Hengband¤Î'lib'¥Õ¥©¥ë¥À¤¬Â¸ºß¤·¤Ê¤¤¤«Àµ¤·¤¯Ìµ¤¤²ÄǽÀ­¤¬¤¢¤ê¤Þ¤¹.");
7081 #else
7082                 plog("The Angband 'lib' folder is probably missing or misplaced.");
7083 #endif
7084
7085                 /* Warning */
7086 #ifdef JP
7087                 plog("Please 'open' any file in any sub-folder of the 'lib' folder.");
7088 #else
7089                 plog("Please 'open' any file in any sub-folder of the 'lib' folder.");
7090 #endif
7091                 
7092 #if TARGET_API_MAC_CARBON
7093                 /* Ask the user to choose the lib folder */
7094                 err = NavGetDefaultDialogOptions(&dialogOptions);
7095
7096                 /* Paranoia */
7097                 if (err != noErr) quit(NULL);
7098
7099                 /* Set default location option */
7100                 dialogOptions.dialogOptionFlags |= kNavSelectDefaultLocation;
7101
7102                 /* Clear preview option */
7103                 dialogOptions.dialogOptionFlags &= ~(kNavAllowPreviews);
7104
7105                 /* Forbit selection of multiple files */
7106                 dialogOptions.dialogOptionFlags &= ~(kNavAllowMultipleFiles);
7107
7108                 /* Display location */
7109                 dialogOptions.location = topleft;
7110
7111                 /* Load the message for the missing folder from the resource fork */
7112                 GetIndString(dialogOptions.message, 128, 1);
7113
7114                 /* Wait for the user to choose a folder */
7115                 err = NavChooseFolder(
7116                         nil,
7117                         &theReply,
7118                         &dialogOptions,
7119                         nil,
7120                         nil,
7121                         nil);
7122
7123                 /* Assume the player doesn't want to go on */
7124                 if ((err != noErr) || !theReply.validRecord) quit(NULL);
7125
7126                 /* Retrieve FSSpec from the reply */
7127                 {
7128                         AEKeyword theKeyword;
7129                         DescType actualType;
7130                         Size actualSize;
7131
7132                         /* Get a pointer to selected folder */
7133                         err = AEGetNthPtr(
7134                                 &(theReply.selection),
7135                                 1,
7136                                 typeFSS,
7137                                 &theKeyword,
7138                                 &actualType,
7139                                 &theFolderSpec,
7140                                 sizeof(FSSpec),
7141                                 &actualSize);
7142
7143                         /* Paranoia */
7144                         if (err != noErr) quit(NULL);
7145                 }
7146
7147                 /* Free navitagor reply */
7148                 err = NavDisposeReply(&theReply);
7149
7150                 /* Paranoia */
7151                 if (err != noErr) quit(NULL);
7152
7153                 /* Extract textual file name for given file */
7154                 refnum_to_name(
7155                         path,
7156                         theFolderSpec.parID,
7157                         theFolderSpec.vRefNum,
7158                         (char *)theFolderSpec.name);
7159 #else
7160                 /* Allow "text" files */
7161                 types[0] = 'TEXT';
7162
7163                 /* Allow "save" files */
7164                 types[1] = 'SAVE';
7165
7166                 /* Allow "data" files */
7167                 types[2] = 'DATA';
7168
7169                 /* Get any file */
7170                 SFGetFile(topleft, "\p", NULL, 3, types, NULL, &reply);
7171
7172                 /* Allow cancel */
7173                 if (!reply.good) quit(NULL);
7174
7175                 /* Extract textual file name for given file */
7176                 GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
7177                 refnum_to_name(path, drefnum, vrefnum, (char*)reply.fName);
7178 #endif
7179
7180                 /* Hack -- Remove the "filename" */
7181                 i = strlen(path) - 1;
7182                 while ((i > 0) && (path[i] != ':')) i--;
7183                 if (path[i] == ':') path[i+1] = '\0';
7184
7185                 /* Hack -- allow "lib" folders */
7186                 if (suffix(path, "lib:")) continue;
7187
7188                 /* Hack -- Remove the "sub-folder" */
7189                 i = i - 1;
7190                 while ((i > 1) && (path[i] != ':')) i--;
7191                 if (path[i] == ':') path[i+1] = '\0';
7192         }
7193 }
7194
7195
7196 /*
7197  * Macintosh Main loop
7198  */
7199 int main(void)
7200 {
7201         EventRecord tempEvent;
7202         int numberOfMasters = 10;
7203
7204 #if !TARGET_API_MAC_CARBON
7205         /* Increase stack space by 64K */
7206         SetApplLimit(GetApplLimit() - 131072L);//65536L);
7207
7208         /* Stretch out the heap to full size */
7209         MaxApplZone();
7210 #endif
7211
7212         /* Get more Masters */
7213         while (numberOfMasters--) MoreMasters();
7214
7215 #if !TARGET_API_MAC_CARBON
7216         /* Set up the Macintosh */
7217         InitGraf(&qd.thePort);
7218         InitFonts();
7219         InitWindows();
7220         InitMenus();
7221         /* TEInit(); */
7222         InitDialogs(NULL);
7223 #endif
7224         InitCursor();
7225
7226 #ifdef JP
7227         KeyScript(smRoman);
7228 #endif
7229
7230         /* Flush events */
7231         FlushEvents(everyEvent, 0);
7232
7233         /* Flush events some more (?) */
7234         (void)EventAvail(everyEvent, &tempEvent);
7235         (void)EventAvail(everyEvent, &tempEvent);
7236         (void)EventAvail(everyEvent, &tempEvent);
7237
7238
7239 #ifdef ANGBAND_LITE_MAC
7240
7241         /* Nothing */
7242
7243 #else /* ANGBAND_LITE_MAC */
7244
7245 # if defined(powerc) || defined(__powerc)
7246
7247         /* Assume System 7 */
7248         
7249         /* Assume Color Quickdraw */
7250
7251 # else
7252
7253 #if TARGET_API_MAC_CARBON
7254
7255         {
7256                 OSErr err;
7257                 long response;
7258
7259                 /* Check for existence of Carbon */
7260                 err = Gestalt(gestaltCarbonVersion, &response);
7261
7262                 if (err != noErr) quit("This program requires Carbon API");
7263         }
7264
7265 #else
7266         /* Block */
7267         if (TRUE)
7268         {
7269                 OSErr err;
7270                 long versionNumber;
7271
7272                 /* Check the Gestalt */
7273                 err = Gestalt(gestaltSystemVersion, &versionNumber);
7274
7275                 /* Check the version */
7276                 if ((err != noErr) || (versionNumber < 0x0700))
7277                 {
7278                         #ifdef JP
7279                         quit("¤³¤Î¥×¥í¥°¥é¥à¤Ï´Á»úTalk7.x.x°Ê¹ß¤ÇÆ°ºî¤·¤Þ¤¹.");
7280                         #else
7281                         quit("You must have System 7 to use this program.");
7282                         #endif
7283                 }
7284         }
7285
7286         /* Block */
7287         if (TRUE)
7288         {
7289                 SysEnvRec env;
7290
7291                 /* Check the environs */
7292                 if (SysEnvirons(1, &env) != noErr)
7293                 {
7294                         #ifdef JP
7295                         quit("SysEnvirons ¥³¡¼¥ë¤Ï¼ºÇÔ¤·¤Þ¤·¤¿¡ª");
7296                         #else
7297                         quit("The SysEnvirons call failed!");
7298                         #endif
7299                 }
7300
7301                 /* Check for System Seven Stuff */
7302                 if (env.systemVersion < 0x0700)
7303                 {
7304                         #ifdef JP
7305                         quit("¤³¤Î¥×¥í¥°¥é¥à¤Ï´Á»úTalk7.x.x°Ê¹ß¤ÇÆ°ºî¤·¤Þ¤¹.");
7306                         #else
7307                         quit("You must have System 7 to use this program.");
7308                         #endif
7309                 }
7310
7311                 /* Check for Color Quickdraw */
7312                 if (!env.hasColorQD)
7313                 {
7314                         #ifdef JP
7315                         quit("¤³¤Î¥×¥í¥°¥é¥à¤ÏColor Quickdraw¤¬Ìµ¤¤¤ÈÆ°ºî¤·¤Þ¤»¤ó.");
7316                         #else
7317                         quit("You must have Color Quickdraw to use this program.");
7318                         #endif
7319                 }
7320         }
7321
7322 #endif /* CARBON */
7323 #endif
7324
7325 #endif /* ANGBAND_LITE_MAC */
7326
7327         /* 
7328          * Remember Mac OS version, in case we have to cope with version-specific
7329          * problems
7330          */
7331         (void)Gestalt(gestaltSystemVersion, &mac_os_version);
7332
7333 #ifdef USE_SFL_CODE
7334         /* Obtain a "Universal Procedure Pointer" */
7335         AEH_Start_UPP = NewAEEventHandlerUPP(AEH_Start);
7336         /* Install the hook (ignore error codes) */
7337         AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, AEH_Start_UPP,
7338                               0L, FALSE);
7339
7340         /* Obtain a "Universal Procedure Pointer" */
7341         AEH_Quit_UPP = NewAEEventHandlerUPP(AEH_Quit);
7342         /* Install the hook (ignore error codes) */
7343         AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, AEH_Quit_UPP,
7344                               0L, FALSE);
7345
7346         /* Obtain a "Universal Procedure Pointer" */
7347         AEH_Print_UPP = NewAEEventHandlerUPP(AEH_Print);
7348         /* Install the hook (ignore error codes) */
7349         AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, AEH_Print_UPP,
7350                               0L, FALSE);
7351
7352         /* Obtain a "Universal Procedure Pointer" */
7353         AEH_Open_UPP = NewAEEventHandlerUPP(AEH_Open);
7354         /* Install the hook (ignore error codes) */
7355         AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, AEH_Open_UPP,
7356                               0L, FALSE);
7357 #endif
7358
7359 #ifndef MACH_O_CARBON
7360         /* Find the current application */
7361         SetupAppDir();
7362 #endif
7363
7364         /* Mark ourself as the file creator */
7365         _fcreator = ANGBAND_CREATOR;
7366
7367         /* Default to saving a "text" file */
7368         _ftype = 'TEXT';
7369
7370
7371 #if defined(__MWERKS__)
7372
7373         /* Obtian a "Universal Procedure Pointer" */
7374 #if TARGET_API_MAC_CARBON
7375         ynfilterUPP = NewModalFilterUPP(ynfilter);
7376 #else
7377         ynfilterUPP = NewModalFilterProc(ynfilter);
7378 #endif
7379
7380 #endif
7381
7382
7383         /* Hook in some "z-virt.c" hooks */
7384         rnfree_aux = hook_rnfree;
7385         ralloc_aux = hook_ralloc;
7386         rpanic_aux = hook_rpanic;
7387
7388         /* Hooks in some "z-util.c" hooks */
7389         plog_aux = hook_plog;
7390         quit_aux = hook_quit;
7391         core_aux = hook_core;
7392
7393         BackColor(blackColor);
7394         ForeColor(whiteColor);
7395
7396         /* Show the "watch" cursor */
7397         SetCursor(*(GetCursor(watchCursor)));
7398
7399         /* Prepare the menubar */
7400         init_menubar();
7401
7402         /* Prepare the windows */
7403         init_windows();
7404
7405 #ifndef MACH_O_CARBON
7406
7407         init_sound();
7408
7409         init_graf();
7410
7411 #endif
7412         
7413         /* Hack -- process all events */
7414         while (CheckEvents(TRUE)) /* loop */;
7415
7416         /* Reset the cursor */
7417 #if TARGET_API_MAC_CARBON
7418         {
7419                 Cursor  arrow;
7420                 GetQDGlobalsArrow( &arrow );
7421                 SetCursor(&arrow);
7422         }
7423 #else
7424         SetCursor( &qd.arrow );
7425 #endif
7426
7427
7428         /* Mega-Hack -- Allocate a "lifeboat" */
7429         lifeboat = NewPtr(16384);
7430
7431 #ifdef USE_QT_SOUND
7432
7433         /* Load sound effect resources */
7434         load_sounds();
7435
7436 #endif /* USE_QT_SOUND */
7437
7438         /* Note the "system" */
7439         ANGBAND_SYS = "mac";
7440
7441         /* Initialize */
7442         init_stuff();
7443
7444         /* Catch nasty signals */
7445         signals_init();
7446
7447         /* Initialize */
7448         init_angband();
7449
7450
7451         /* Hack -- process all events */
7452         while (CheckEvents(TRUE)) /* loop */;
7453
7454
7455         /* We are now initialized */
7456         initialized = TRUE;
7457
7458
7459         /* Handle "open_when_ready" */
7460         handle_open_when_ready();
7461
7462 #ifdef CHUUKEI
7463         init_chuukei();
7464 #endif
7465
7466         /* Prompt the user */
7467 #ifdef JP
7468         prt("'¥Õ¥¡¥¤¥ë'¥á¥Ë¥å¡¼¤è¤ê'¿·µ¬'¤Þ¤¿¤Ï'³«¤¯...'¤òÁªÂò¤·¤Æ¤¯¤À¤µ¤¤¡£", 23, 10);
7469 #else
7470         prt("[Choose 'New' or 'Open' from the 'File' menu]", 23, 15);
7471 #endif
7472
7473         /* Flush the prompt */
7474         Term_fresh();
7475
7476
7477         /* Hack -- Process Events Forever */
7478         while (TRUE) CheckEvents(TRUE);
7479 }
7480