OSDN Git Service

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