OSDN Git Service

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