OSDN Git Service

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