OSDN Git Service

Kuwa氏より提供されたmain-mac.cを反映し, Mac版で初期設定が保存されない
[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 #ifdef 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 #if TARGET_API_MAC_CARBON
2883         /* Item "arg_sound" */
2884         CheckMenuItem(m, 1, arg_sound);
2885
2886         /* Item "arg_graphics" */
2887         CheckMenuItem(m, 2, arg_graphics);
2888         
2889         /* Item "arg_newstyle_graphics"*/
2890         CheckMenuItem(m, 8, arg_newstyle_graphics);
2891 #else
2892         /* Item "arg_sound" */
2893         CheckItem(m, 1, arg_sound);
2894
2895         /* Item "arg_graphics" */
2896         CheckItem(m, 2, arg_graphics);
2897         
2898         /* Item "arg_newstyle_graphics"*/
2899         CheckItem(m, 8, arg_newstyle_graphics);
2900 #endif
2901
2902         /* Windows */
2903         for (i = 0; i < MAX_TERM_DATA; i++)
2904         {
2905                 /* Access */
2906                 td = &data[i];
2907
2908                 td->mapped = getshort();
2909
2910                 td->font_id = getshort();
2911                 td->font_size = getshort();
2912                 td->font_face = getshort();
2913
2914                 td->tile_wid = getshort();
2915                 td->tile_hgt = getshort();
2916
2917                 td->cols = getshort();
2918                 td->rows = getshort();
2919
2920                 td->r.left = getshort();
2921                 td->r.top = getshort();
2922
2923                 /* Done */
2924                 if (feof(fff)) break;
2925         }
2926 }
2927 #endif /* TARGET_API_MAC_CARBON */
2928
2929
2930
2931 /*
2932  * Hack -- default data for a window
2933  */
2934 static void term_data_hack(term_data *td)
2935 {
2936         short fid;
2937
2938 #if TARGET_API_MAC_CARBON
2939 #ifdef JP
2940         /* Default to Osaka font (Japanese) */
2941         fid = FMGetFontFamilyFromName( "\pOsaka¡ÝÅùÉý" );
2942 #else
2943         /* Default to Monaco font */
2944         fid = FMGetFontFamilyFromName("\pmonaco");
2945 #endif
2946 #else
2947 #ifdef JP
2948         /* Default to ÅùÉýÌÀÄ« font (Japanese) */
2949         GetFNum( "\pÅùÉýÌÀÄ«", &fid);
2950         SetFScaleDisable( true );
2951 #else
2952         /* Default to Monaco font */
2953         GetFNum("\pmonaco", &fid);
2954 #endif
2955 #endif
2956
2957         /* Wipe it */
2958         WIPE(td, term_data);
2959
2960         /* No color */
2961         td->last = -1;
2962
2963         /* Default borders */
2964         td->size_ow1 = 2;
2965         td->size_ow2 = 2;
2966         td->size_oh2 = 2;
2967
2968         /* Start hidden */
2969         td->mapped = FALSE;
2970
2971         /* Default font */
2972         td->font_id = fid;
2973
2974         /* Default font size */
2975         td->font_size = 12;
2976
2977         /* Default font face */
2978         td->font_face = 0;
2979
2980         /* Default size */
2981         td->rows = 24;
2982         td->cols = 80;
2983
2984         /* Default position */
2985         td->r.left = 10;
2986         td->r.top = 40;
2987
2988         /* Minimal keys */
2989         td->keys = 16;
2990 }
2991
2992
2993 /*
2994  * Read the preference file, Create the windows.
2995  *
2996  * We attempt to use "FindFolder()" to track down the preference file,
2997  * but if this fails, for any reason, we will try the "SysEnvirons()"
2998  * method, which may work better with System 6.
2999  */
3000 static void init_windows(void)
3001 {
3002         int i, b = 0;
3003
3004         term_data *td;
3005
3006         SysEnvRec env;
3007         short savev;
3008         long saved;
3009
3010         bool oops;
3011
3012
3013         /*** Default values ***/
3014
3015         /* Initialize (backwards) */
3016         for (i = MAX_TERM_DATA - 1; i >= 0; i--)
3017         {
3018                 int n;
3019
3020                 cptr s;
3021
3022                 /* Obtain */
3023                 td = &data[i];
3024
3025                 /* Defaults */
3026                 term_data_hack(td);
3027
3028                 /* Obtain title */
3029                 s = angband_term_name[i];
3030
3031                 /* Get length */
3032                 n = strlen(s);
3033
3034                 /* Maximal length */
3035                 if (n > 15) n = 15;
3036
3037                 /* Copy the title */
3038                 strncpy((char*)(td->title) + 1, s, n);
3039
3040                 /* Save the length */
3041                 td->title[0] = n;
3042
3043                 /* Tile the windows */
3044                 td->r.left += (b * 30);
3045                 td->r.top += (b * 30);
3046
3047                 /* Tile */
3048                 b++;
3049         }
3050
3051
3052         /*** Load preferences ***/
3053         
3054 #ifdef TARGET_API_MAC_CARBON
3055         cf_load_prefs();
3056 #else
3057         /* Assume failure */
3058         oops = TRUE;
3059
3060         /* Assume failure */
3061         fff = NULL;
3062
3063 #ifdef USE_SFL_CODE
3064
3065         /* Block */
3066         if (TRUE)
3067         {
3068                 OSErr   err;
3069                 short   vref;
3070                 long    dirID;
3071                 char    foo[128];
3072
3073                 /* Find the folder */
3074                 err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
3075                                  &vref, &dirID);
3076
3077                 /* Success */
3078                 if (!err)
3079                 {
3080                         /* Extract a path name */
3081                         PathNameFromDirID(dirID, vref, (StringPtr)foo);
3082
3083                         /* Convert the string */
3084                         ptocstr((StringPtr)foo);
3085
3086                         /* Append the preference file name */
3087                         strcat(foo, PREF_FILE_NAME);
3088
3089                         /* Open the preference file */
3090                         fff = fopen(foo, "r");
3091
3092                         /* Success */
3093                         oops = FALSE;
3094                 }
3095         }
3096
3097 #endif /* USE_SFL_CODE */
3098
3099         /* Oops */
3100         if (oops)
3101         {
3102                 /* Save */
3103                 HGetVol(0, &savev, &saved);
3104
3105                 /* Go to the "system" folder */
3106                 SysEnvirons(curSysEnvVers, &env);
3107                 SetVol(0, env.sysVRefNum);
3108
3109                 /* Open the file */
3110                 fff = fopen(PREF_FILE_NAME, "r");
3111
3112                 /* Restore */
3113                 HSetVol(0, savev, saved);
3114         }
3115
3116         /* Load preferences */
3117         if (fff)
3118         {
3119                 /* Load a real preference file */
3120                 load_prefs();
3121
3122                 /* Close the file */
3123                 my_fclose(fff);
3124         }
3125 #endif
3126
3127
3128         /*** Instantiate ***/
3129
3130         /* Main window */
3131         td = &data[0];
3132
3133         /* Many keys */
3134         td->keys = 1024;
3135
3136         /* Start visible */
3137         td->mapped = TRUE;
3138
3139         /* Link (backwards, for stacking order) */
3140         for (i = MAX_TERM_DATA - 1; i >= 0; i--)
3141         {
3142                 term_data_link(i);
3143         }
3144
3145         /* Main window */
3146         td = &data[0];
3147
3148         /* Main window */
3149         Term_activate(td->t);
3150 }
3151
3152 static void init_sound( void )
3153 {
3154         int err, i;
3155         CInfoPBRec pb;
3156         SignedByte              permission = fsRdPerm;
3157         pascal short    ret;
3158         
3159         Handle handle;
3160         Str255 sound;
3161
3162         /* Descend into "lib" folder */
3163         pb.dirInfo.ioCompletion = NULL;
3164         pb.dirInfo.ioNamePtr = "\plib";
3165         pb.dirInfo.ioVRefNum = app_vol;
3166         pb.dirInfo.ioDrDirID = app_dir;
3167         pb.dirInfo.ioFDirIndex = 0;
3168
3169         /* Check for errors */
3170         err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3171
3172         /* Success */
3173         if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3174         {
3175                 /* Descend into "lib/save" folder */
3176                 pb.dirInfo.ioCompletion = NULL;
3177                 pb.dirInfo.ioNamePtr = "\pxtra";
3178                 pb.dirInfo.ioVRefNum = app_vol;
3179                 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3180                 pb.dirInfo.ioFDirIndex = 0;
3181
3182                 /* Check for errors */
3183                 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3184                         
3185                         /* Success */
3186                 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3187                 {
3188                         /* Descend into "lib/save" folder */
3189                         pb.dirInfo.ioCompletion = NULL;
3190                         pb.dirInfo.ioNamePtr = "\psound";
3191                         pb.dirInfo.ioVRefNum = app_vol;
3192                         pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3193                         pb.dirInfo.ioFDirIndex = 0;
3194
3195                         /* Check for errors */
3196                         err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3197
3198                         /* Success */
3199                         if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3200                         {
3201                                 ret = HOpenResFile( app_vol , pb.dirInfo.ioDrDirID , "\psound.rsrc" , permission );
3202                                 if( ret != -1 ){
3203                                         ext_sound = 1;
3204                                         
3205                                         for( i = 0 ; i < 7 ; i++ )
3206                                                         soundmode[i] = false;
3207                                         
3208                                         for( i = 1 ; i < SOUND_MAX ; i++ ){
3209                                                 /* Get the proper sound name */
3210                                                 sprintf((char*)sound + 1, "%.16s.wav", angband_sound_name[i]);
3211                                                 sound[0] = strlen((char*)sound + 1);
3212
3213                                                 /* Obtain resource XXX XXX XXX */
3214                                                 handle = Get1NamedResource('snd ', sound);
3215                                                 if( handle == NULL || ext_sound )
3216                                                         handle = GetNamedResource('snd ', sound);
3217                                                 
3218                                                 if( handle )
3219                                                         soundmode[soundchoice[i]] = true;
3220                                                 
3221                                         }
3222                                 }
3223                         }
3224                 }
3225         }
3226 }
3227
3228 static void init_graf( void )
3229 {
3230         int err, i;
3231         CInfoPBRec pb;
3232         SignedByte              permission = fsRdPerm;
3233         pascal short    ret;
3234         
3235         Handle handle;
3236         Str255 graf;
3237
3238         /* Descend into "lib" folder */
3239         pb.dirInfo.ioCompletion = NULL;
3240         pb.dirInfo.ioNamePtr = "\plib";
3241         pb.dirInfo.ioVRefNum = app_vol;
3242         pb.dirInfo.ioDrDirID = app_dir;
3243         pb.dirInfo.ioFDirIndex = 0;
3244
3245         /* Check for errors */
3246         err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3247
3248         /* Success */
3249         if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3250         {
3251                 /* Descend into "lib/xtra" folder */
3252                 pb.dirInfo.ioCompletion = NULL;
3253                 pb.dirInfo.ioNamePtr = "\pxtra";
3254                 pb.dirInfo.ioVRefNum = app_vol;
3255                 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3256                 pb.dirInfo.ioFDirIndex = 0;
3257
3258                 /* Check for errors */
3259                 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3260                         
3261                 /* Success */
3262                 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3263                 {
3264                         /* Descend into "lib/xtra/graf" folder */
3265                         pb.dirInfo.ioCompletion = NULL;
3266                         pb.dirInfo.ioNamePtr = "\pgraf";
3267                         pb.dirInfo.ioVRefNum = app_vol;
3268                         pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3269                         pb.dirInfo.ioFDirIndex = 0;
3270
3271                         /* Check for errors */
3272                         err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3273
3274                         /* Success */
3275                         if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3276                         {
3277                                 ret = HOpenResFile( app_vol , pb.dirInfo.ioDrDirID , "\pgraf.rsrc" , permission );
3278                                 if (ret != -1)
3279                                 {
3280                                         ext_graf = 1;
3281
3282                                         /* Obtain resource XXX XXX XXX */
3283                                         handle = Get1NamedResource('PICT', graf);
3284                                         if ( handle == NULL || ext_graf )
3285                                                 handle = GetNamedResource('PICT', "\pgraf.rsrc");
3286                                 }
3287                         }
3288                 }
3289         }
3290 }
3291
3292 #ifdef CHUUKEI
3293 /*
3294
3295 */
3296 static void init_chuukei( void )
3297 {
3298         char path[1024];
3299         char tmp[1024];
3300         FILE *fp;
3301         
3302         path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "chuukei.txt");
3303
3304         fp = fopen(path, "r");
3305         if(!fp)
3306                 return;
3307         
3308         /* Read a line */
3309         if (fgets(tmp, 1024, fp)){
3310                 if(tmp[0] == '-'){
3311                         int n = strlen(tmp);
3312                         tmp[n-1] = 0;
3313                         switch(tmp[1]){
3314                         case 'p':
3315                         {
3316                                 if (!tmp[2]) break;
3317                                 chuukei_server = TRUE;
3318                                 if(connect_chuukei_server(&tmp[2])<0){
3319                                         msg_print("connect fail");
3320                                         return;
3321                                 }
3322                                 msg_print("connect");
3323                                 msg_print(NULL);
3324                                 break;
3325                         }
3326
3327                         case 'c':
3328                         {
3329                                 chuukei_client = TRUE;
3330                                 connect_chuukei_server(&tmp[2]);
3331                                 play_game(FALSE);
3332                                 quit(NULL);
3333                         }
3334                         }
3335                 }
3336                 
3337         }
3338         fclose(fp);
3339         
3340 }
3341 #endif
3342
3343 /*
3344
3345 */
3346 short InevrtCheck( DialogPtr targetDlg, short check )
3347 {
3348         Handle  checkH;
3349         short   itemType;
3350         long    result;
3351         Rect    box;
3352         
3353         GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
3354         result = (GetControlValue( (ControlHandle)checkH ) + 1 ) % 2;
3355         SetControlValue( (ControlHandle)checkH , result );
3356         return result ;
3357
3358 }
3359
3360 /*
3361
3362 */
3363 short SetCheck( DialogPtr targetDlg, short check, long result )
3364 {
3365         Handle  checkH;
3366         short   itemType;
3367
3368         Rect    box;
3369         
3370         GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
3371         SetControlValue( (ControlHandle)checkH , result );
3372         return result ;
3373
3374 }
3375
3376 /*
3377
3378 */
3379 short GetCheck( DialogPtr targetDlg, short check )
3380 {
3381         Handle  checkH;
3382         short   itemType;
3383         long    result;
3384         Rect    box;
3385         
3386         GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
3387         result = GetControlValue( (ControlHandle)checkH );
3388         return result ;
3389
3390 }
3391 void SoundConfigDLog(void)
3392 {
3393         DialogPtr dialog;
3394         Rect r;
3395         short item_hit;
3396         int     i;
3397
3398         dialog=GetNewDialog(131, 0, (WindowPtr)-1);
3399         SetDialogDefaultItem( dialog, ok );
3400         SetDialogCancelItem( dialog, cancel );
3401         for( i = 1 ; i < 7 ; i++ )
3402                 SetCheck( dialog, i+2 , soundmode[i] );
3403         
3404         /* ShowWindow(dialog); */ 
3405         for( item_hit = 100 ; cancel < item_hit ; ){
3406                 ModalDialog(0, &item_hit);
3407                 
3408                 switch(item_hit){
3409                         case ok:
3410                                 for( i = 1 ; i < 7 ; i++ )
3411                                         soundmode[i] = GetCheck( dialog, i+2 );
3412                                 break;
3413                         case cancel:
3414                                 break;
3415                         default:
3416                                 InevrtCheck( dialog, item_hit );
3417                 }
3418         }
3419         DisposeDialog(dialog);
3420
3421 }
3422
3423
3424 /*
3425  * Exit the program
3426  */
3427 #if TARGET_API_MAC_CARBON
3428 static void save_pref_file(void)
3429 {
3430         cf_save_prefs();
3431 }
3432 #else
3433 static void save_pref_file(void)
3434 {
3435         bool oops;
3436
3437         SysEnvRec env;
3438         short savev;
3439         long saved;
3440
3441
3442         /* Assume failure */
3443         oops = TRUE;
3444
3445         /* Assume failure */
3446         fff = NULL;
3447
3448         /* Text file */
3449         _ftype = 'TEXT';
3450
3451
3452 #ifdef USE_SFL_CODE
3453
3454         /* Block */
3455         if (TRUE)
3456         {
3457                 OSErr   err;
3458                 short   vref;
3459                 long    dirID;
3460                 char    foo[128];
3461
3462                 /* Find the folder */
3463                 err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
3464                                  &vref, &dirID);
3465
3466                 /* Success */
3467                 if (!err)
3468                 {
3469                         /* Extract a path name */
3470                         PathNameFromDirID(dirID, vref, (StringPtr)foo);
3471
3472                         /* Convert the string */
3473                         ptocstr((StringPtr)foo);
3474
3475                         /* Append the preference file name */
3476                         strcat(foo, PREF_FILE_NAME);
3477
3478                         /* Open the preference file */
3479                         /* my_fopen set file type and file creator for MPW */
3480                         fff = my_fopen(foo, "w");
3481
3482                         /* Success */
3483                         oops = FALSE;
3484                 }
3485         }
3486
3487 #endif /* USE_SFL_CODE */
3488
3489         /* Oops */
3490         if (oops)
3491         {
3492                 /* Save */
3493                 HGetVol(0, &savev, &saved);
3494
3495                 /* Go to "system" folder */
3496                 SysEnvirons(curSysEnvVers, &env);
3497                 SetVol(0, env.sysVRefNum);
3498
3499                 /* Open the preference file */
3500                 /* my_fopen set file type and file creator for MPW */
3501                 fff = fopen(PREF_FILE_NAME, "w");
3502
3503                 /* Restore */
3504                 HSetVol(0, savev, saved);
3505         }
3506
3507         /* Save preferences */
3508         if (fff)
3509         {
3510                 /* Write the preferences */
3511                 save_prefs();
3512
3513                 /* Close it */
3514                 my_fclose(fff);
3515         }
3516 }
3517 #endif
3518
3519
3520
3521 /*
3522  * A simple "Yes/No" filter to parse "key press" events in dialog windows
3523  */
3524 static pascal Boolean ynfilter(DialogPtr dialog, EventRecord *event, short *ip)
3525 {
3526         /* Parse key press events */
3527         if (event->what == keyDown)
3528         {
3529                 int i = 0;
3530                 char c;
3531
3532                 /* Extract the pressed key */
3533                 c = (event->message & charCodeMask);
3534
3535                 /* Accept "no" and <return> and <enter> */
3536                 if ((c=='n') || (c=='N') || (c==13) || (c==3)) i = 1;
3537
3538                 /* Accept "yes" */
3539                 else if ((c=='y') || (c=='Y')) i = 2;
3540
3541                 /* Handle "yes" or "no" */
3542                 if (i)
3543                 {
3544                         short type;
3545                         ControlHandle control;
3546                         Rect r;
3547
3548                         /* Get the button */
3549                         GetDialogItem(dialog, i, &type, (Handle*)&control, &r);
3550
3551                         /* Blink button for 1/10 second */
3552                         HiliteControl(control, 1);
3553                         Term_xtra_mac(TERM_XTRA_DELAY, 100);
3554                         HiliteControl(control, 0);
3555
3556                         /* Result */
3557                         *ip = i;
3558                         return (1);
3559                 }
3560         }
3561
3562         /* Ignore */
3563         return (0);
3564 }
3565
3566
3567 /*
3568  * Handle menu: "File" + "New"
3569  */
3570 static void do_menu_file_new(void)
3571 {
3572         /* Hack */
3573         HiliteMenu(0);
3574
3575         /* Game is in progress */
3576         game_in_progress = 1;
3577
3578         /* Flush input */
3579         flush();
3580
3581         /* Play a game */
3582         play_game(TRUE);
3583
3584         /* Hack -- quit */
3585         quit(NULL);
3586 }
3587
3588
3589 /*
3590  * Handle menu: "File" + "Open"
3591  */
3592 #if TARGET_API_MAC_CARBON
3593 static void do_menu_file_open(bool all)
3594 {
3595         int err;
3596         short vrefnum;
3597         long drefnum;
3598         long junk;
3599         DirInfo pb;
3600         SFTypeList types;
3601         SFReply reply;
3602         Point topleft;
3603         BitMap screen;
3604         FSSpec  fsp;
3605         char path[1024];
3606         
3607         refnum_to_name(path, app_dir, app_vol, (char*)("\plib:save:"));
3608         
3609         FSpLocationFromFullPath( strlen(path), path, &fsp );
3610         
3611         /* Get any file */
3612         ChooseFile( (StringPtr)savefile, fsp );
3613         
3614         /* Allow cancel */
3615         if (err != noErr) return;
3616
3617         /* Extract textual file name for save file */
3618 /*      GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
3619         refnum_to_name(savefile, drefnum, vrefnum, (char*)reply.fName);
3620 */
3621         /* Hack */
3622         HiliteMenu(0);
3623
3624         /* Game is in progress */
3625         game_in_progress = 1;
3626
3627         /* Flush input */
3628         flush();
3629
3630         /* Play a game */
3631         play_game(FALSE);
3632
3633         /* Hack -- quit */
3634         quit(NULL);
3635 }
3636 #else
3637 static void do_menu_file_open(bool all)
3638 {
3639         int err;
3640         short vrefnum;
3641         long drefnum;
3642         long junk;
3643         DirInfo pb;
3644         SFTypeList types;
3645         SFReply reply;
3646         Point topleft;
3647
3648
3649         /* XXX XXX XXX */
3650
3651         /* vrefnum = GetSFCurVol(); */
3652         vrefnum = -*((short*)0x214);
3653
3654         /* drefnum = GetSFCurDir(); */
3655         drefnum = *((long*)0x398);
3656
3657         /* Descend into "lib" folder */
3658         pb.ioCompletion = NULL;
3659         pb.ioNamePtr = "\plib";
3660         pb.ioVRefNum = vrefnum;
3661         pb.ioDrDirID = drefnum;
3662         pb.ioFDirIndex = 0;
3663
3664         /* Check for errors */
3665         err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3666
3667         /* Success */
3668         if ((err == noErr) && (pb.ioFlAttrib & 0x10))
3669         {
3670                 /* Descend into "lib/save" folder */
3671                 pb.ioCompletion = NULL;
3672                 pb.ioNamePtr = "\psave";
3673                 pb.ioVRefNum = vrefnum;
3674                 pb.ioDrDirID = pb.ioDrDirID;
3675                 pb.ioFDirIndex = 0;
3676
3677                 /* Check for errors */
3678                 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3679
3680                 /* Success */
3681                 if ((err == noErr) && (pb.ioFlAttrib & 0x10))
3682                 {
3683                         /* SetSFCurDir(pb.ioDrDirID); */
3684                         *((long*)0x398) = pb.ioDrDirID;
3685                 }
3686         }
3687
3688         /* Window location */
3689         topleft.h = (qd.screenBits.bounds.left+qd.screenBits.bounds.right)/2-344/2;
3690         topleft.v = (2*qd.screenBits.bounds.top+qd.screenBits.bounds.bottom)/3-188/2;
3691
3692         /* Allow "all" files */
3693         if (all)
3694         {
3695                 /* Get any file */
3696                 SFGetFile(topleft, "\p", NULL, -1, types, NULL, &reply);
3697         }
3698
3699         /* Allow "save" files */
3700         else
3701         {
3702                 /* Legal types */
3703                 types[0] = 'SAVE';
3704
3705                 /* Get a file */
3706                 SFGetFile(topleft, "\p", NULL, 1, types, NULL, &reply);
3707         }
3708
3709         /* Allow cancel */
3710         if (!reply.good) return;
3711
3712         /* Extract textual file name for save file */
3713         GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
3714         refnum_to_name(savefile, drefnum, vrefnum, (char*)reply.fName);
3715
3716         /* Hack */
3717         HiliteMenu(0);
3718
3719         /* Game is in progress */
3720         game_in_progress = 1;
3721
3722         /* Flush input */
3723         flush();
3724
3725         /* Play a game */
3726         play_game(FALSE);
3727
3728         /* Hack -- quit */
3729         quit(NULL);
3730 }
3731 #endif
3732
3733
3734 /*
3735  * Handle the "open_when_ready" flag
3736  */
3737 static void handle_open_when_ready(void)
3738 {
3739         /* Check the flag XXX XXX XXX make a function for this */
3740         if (open_when_ready && initialized && !game_in_progress)
3741         {
3742                 /* Forget */
3743                 open_when_ready = FALSE;
3744
3745                 /* Game is in progress */
3746                 game_in_progress = 1;
3747
3748                 /* Wait for it */
3749                 pause_line(23);
3750
3751                 /* Flush input */
3752                 flush();
3753
3754                 /* Play a game */
3755                 play_game(FALSE);
3756
3757                 /* Quit */
3758                 quit(NULL);
3759         }
3760 }
3761
3762
3763
3764 /*
3765  * Initialize the menus
3766  *
3767  * Verify menus 128, 129, 130
3768  * Create menus 131, 132, 133, 134
3769  *
3770  * The standard menus are:
3771  *
3772  *   Apple (128) =   { About, -, ... }
3773  *   File (129) =    { New,Open,Import,Close,Save,-,Exit,Quit }
3774  *   Edit (130) =    { Cut, Copy, Paste, Clear }   (?)
3775  *   Font (131) =    { Bold, Extend, -, Monaco, ..., -, ... }
3776  *   Size (132) =    { ... }
3777  *   Window (133) =  { Angband, Mirror, Recall, Choice,
3778  *                     Term-4, Term-5, Term-6, Term-7 }
3779  *   Special (134) = { arg_sound, arg_graphics, -,
3780  *                     arg_fiddle, arg_wizard }
3781  */
3782 static void init_menubar(void)
3783 {
3784         int i, n;
3785
3786         Rect r;
3787
3788         WindowPtr tmpw;
3789
3790         MenuHandle m;
3791         OSErr           err;
3792         long            response;
3793
3794         /* Get the "apple" menu */
3795         m = GetMenu(128);
3796
3797         /* Insert the menu */
3798         InsertMenu(m, 0);
3799
3800         /* Add the DA's to the "apple" menu */
3801 #if TARGET_API_MAC_CARBON
3802 #else
3803         AppendResMenu   (m, 'DRVR');
3804 #endif
3805
3806         /* Get the "File" menu */
3807 #if TARGET_API_MAC_CARBON
3808         m = GetMenu(129);
3809         err = Gestalt( gestaltSystemVersion, &response );
3810         if ( (err == noErr) && (response >= 0x00000A00) )
3811         {
3812                 DeleteMenuItem( m, 7 );
3813         }
3814 #else
3815         m = GetMenu(129);
3816 #endif
3817
3818         /* Insert the menu */
3819         InsertMenu(m, 0);
3820
3821
3822         /* Get the "Edit" menu */
3823         m = GetMenu(130);
3824
3825         /* Insert the menu */
3826         InsertMenu(m, 0);
3827
3828
3829         /* Make the "Font" menu */
3830         #ifdef JP
3831         m = NewMenu(131, "\p¥Õ¥©¥ó¥È");
3832         #else
3833         m = NewMenu(131, "\pFont");
3834         #endif
3835         
3836         /* Insert the menu */
3837         InsertMenu(m, 0);
3838
3839         /* Add "bold" */
3840         AppendMenu(m, "\pBold");
3841
3842         /* Add "wide" */
3843         AppendMenu(m, "\pWide");
3844
3845         /* Add a separator */
3846         AppendMenu(m, "\p-");
3847
3848         /* Fake window */
3849         r.left = r.right = r.top = r.bottom = 0;
3850
3851         /* Make the fake window */
3852         tmpw = NewWindow(0, &r, "\p", false, documentProc, 0, 0, 0);
3853
3854         /* Activate the "fake" window */
3855 #if TARGET_API_MAC_CARBON
3856         SetPortWindowPort(tmpw);
3857 #else
3858         SetPort(tmpw);
3859 #endif
3860
3861         /* Default mode */
3862         TextMode(0);
3863
3864         /* Default size */
3865         TextSize(12);
3866
3867         /* Add the fonts to the menu */
3868         AppendResMenu(m, 'FONT');
3869
3870         /* Size of menu */
3871 #if TARGET_API_MAC_CARBON
3872         n = CountMenuItems(m);
3873 #else
3874         n = CountMItems(m);
3875 #endif
3876
3877         /* Scan the menu */
3878         for (i = n; i >= 4; i--)
3879         {
3880                 Str255 tmpName;
3881                 short fontNum;
3882
3883                 /* Acquire the font name */
3884                 GetMenuItemText(m, i, tmpName);
3885
3886                 /* Acquire the font index */
3887 #if TARGET_API_MAC_CARBON
3888                 fontNum = FMGetFontFamilyFromName( tmpName );
3889 #else
3890                 GetFNum(tmpName, &fontNum);
3891 #endif
3892
3893                 /* Apply the font index */
3894                 TextFont(fontNum);
3895
3896                 /* Remove non-mono-spaced fonts */
3897                 if ((CharWidth('i') != CharWidth('W')) || (CharWidth('W') == 0))
3898                 {
3899                         /* Delete the menu item XXX XXX XXX */
3900                         DeleteMenuItem  (m, i);
3901                 }
3902         }
3903
3904         /* Destroy the old window */
3905         DisposeWindow(tmpw);
3906
3907         /* Add a separator */
3908         AppendMenu(m, "\p-");
3909
3910         /* Add the fonts to the menu */
3911         AppendResMenu   (m, 'FONT');
3912
3913
3914         /* Make the "Size" menu */
3915         #ifdef JP
3916         m = NewMenu(132, "\p¥µ¥¤¥º");
3917         #else
3918         m = NewMenu(132, "\pSize");
3919         #endif
3920         
3921         /* Insert the menu */
3922         InsertMenu(m, 0);
3923
3924         /* Add some sizes (stagger choices) */
3925         for (i = 8; i <= 32; i += ((i / 16) + 1))
3926         {
3927                 Str15 buf;
3928                 
3929                 /* Textual size */
3930                 sprintf((char*)buf + 1, "%d", i);
3931                 buf[0] = strlen((char*)buf + 1);
3932
3933                 /* Add the item */
3934                 AppendMenu(m, buf);
3935         }
3936
3937
3938         /* Make the "Windows" menu */
3939         #ifdef JP
3940         m = NewMenu(133, "\p¥¦¥¤¥ó¥É¥¦");
3941         #else
3942         m = NewMenu(133, "\pWindows");
3943         #endif
3944         
3945         /* Insert the menu */
3946         InsertMenu(m, 0);
3947
3948         /* Default choices */
3949         for (i = 0; i < MAX_TERM_DATA; i++)
3950         {
3951                 Str15 buf;
3952                 
3953                 /* Describe the item */
3954                 sprintf((char*)buf + 1, "%.15s", angband_term_name[i]);
3955                 buf[0] = strlen((char*)buf + 1);
3956
3957                 /* Add the item */
3958                 AppendMenu(m, buf);
3959
3960                 /* Command-Key shortcuts */
3961                 if (i < 8) SetItemCmd(m, i + 1, '0' + i);
3962         }
3963
3964
3965         /* Make the "Special" menu */
3966         #ifdef JP
3967         m = NewMenu(134, "\pÆÃÊÌ");
3968         #else
3969         m = NewMenu(134, "\pSpecial");
3970         #endif
3971         
3972         /* Insert the menu */
3973         InsertMenu(m, 0);
3974
3975         /* Append the choices */
3976         #ifdef JP
3977         AppendMenu(m, "\p¥µ¥¦¥ó¥É»ÈÍÑ");
3978         AppendMenu(m, "\p¥°¥é¥Õ¥£¥Ã¥¯»ÈÍÑ");
3979         AppendMenu(m, "\p-");
3980         AppendMenu(m, "\parg_fiddle");
3981         AppendMenu(m, "\parg_wizard");
3982         AppendMenu(m, "\p-");
3983         AppendMenu(m, "\p¥µ¥¦¥ó¥ÉÀßÄê...");
3984         AppendMenu(m, "\p16X16¥°¥é¥Õ¥£¥Ã¥¯");
3985         AppendMenu(m, "\p£²ÇÜÉý¥¿¥¤¥ëɽ¼¨");
3986         #else
3987         AppendMenu(m, "\parg_sound");
3988         AppendMenu(m, "\parg_graphics");
3989         AppendMenu(m, "\p-");
3990         AppendMenu(m, "\parg_fiddle");
3991         AppendMenu(m, "\parg_wizard");
3992         AppendMenu(m, "\p-");
3993         AppendMenu(m, "\pSound config");
3994         AppendMenu(m, "\pAdam Bolt tile");
3995         AppendMenu(m, "\pBigtile Mode");
3996         #endif
3997
3998         /* Make the "TileWidth" menu */
3999         #ifdef JP
4000         m = NewMenu(135, "\p¥¿¥¤¥ëÉý");
4001         #else
4002         m = NewMenu(135, "\pTileWidth");
4003         #endif
4004
4005         /* Insert the menu */
4006         InsertMenu(m, 0);
4007
4008         /* Add some sizes */
4009         for (i = 4; i <= 32; i++)
4010         {
4011                 Str15 buf;
4012                 
4013                 /* Textual size */
4014                 sprintf((char*)buf + 1, "%d", i);
4015                 buf[0] = strlen((char*)buf + 1);
4016
4017                 /* Append item */
4018                 AppendMenu(m, buf);
4019         }
4020
4021
4022         /* Make the "TileHeight" menu */
4023         #ifdef JP
4024         m = NewMenu(136, "\p¥¿¥¤¥ë¹â");
4025         #else
4026         m = NewMenu(136, "\pTileHeight");
4027         #endif
4028
4029         /* Insert the menu */
4030         InsertMenu(m, 255);
4031
4032         /* Add some sizes */
4033         for (i = 4; i <= 32; i++)
4034         {
4035                 Str15 buf;
4036
4037                 /* Textual size */
4038                 sprintf((char*)buf + 1, "%d", i);
4039                 buf[0] = strlen((char*)buf + 1);
4040
4041                 /* Append item */
4042                 AppendMenu(m, buf);
4043         }
4044
4045
4046         /* Update the menu bar */
4047         DrawMenuBar();
4048 }
4049
4050
4051 /*
4052  * Prepare the menus
4053  */
4054 static void setup_menus(void)
4055 {
4056         int i, n;
4057
4058         short value;
4059
4060         Str255 s;
4061
4062         MenuHandle m;
4063
4064         term_data *td = NULL;
4065
4066
4067         /* Relevant "term_data" */
4068         for (i = 0; i < MAX_TERM_DATA; i++)
4069         {
4070                 /* Unused */
4071                 if (!data[i].t) continue;
4072
4073                 /* Notice the matching window */
4074                 if (data[i].w == FrontWindow()) td = &data[i];
4075         }
4076
4077
4078         /* File menu */
4079         m = GetMenuHandle(129);
4080
4081         /* Get menu size */
4082 #if TARGET_API_MAC_CARBON
4083         n = CountMenuItems(m);
4084 #else
4085         n = CountMItems(m);
4086 #endif
4087
4088         /* Reset menu */
4089         for (i = 1; i <= n; i++)
4090         {
4091                 /* Reset */
4092 #if TARGET_API_MAC_CARBON
4093                 DisableMenuItem(m, i);
4094                 CheckMenuItem(m, i, FALSE);
4095 #else
4096                 DisableItem(m, i);
4097                 CheckItem(m, i, FALSE);
4098 #endif
4099         }
4100
4101         /* Enable "new"/"open..."/"import..." */
4102         if (initialized && !game_in_progress)
4103         {
4104 #if TARGET_API_MAC_CARBON
4105                 EnableMenuItem(m, 1);
4106                 EnableMenuItem(m, 2);
4107                 EnableMenuItem(m, 3);
4108 #else
4109                 EnableItem(m, 1);
4110                 EnableItem(m, 2);
4111                 EnableItem(m, 3);
4112 #endif
4113         }
4114
4115         /* Enable "close" */
4116         if (initialized)
4117         {
4118 #if TARGET_API_MAC_CARBON
4119                 EnableMenuItem(m, 4);
4120 #else
4121                 EnableItem(m, 4);
4122 #endif
4123         }
4124
4125         /* Enable "save" */
4126         if (initialized && character_generated)
4127         {
4128 #if TARGET_API_MAC_CARBON
4129                 EnableMenuItem(m, 5);
4130 #else
4131                 EnableItem(m, 5);
4132 #endif
4133         }
4134
4135         /* Enable "quit" */
4136         if (TRUE)
4137         {
4138 #if TARGET_API_MAC_CARBON
4139                 EnableMenuItem(m, 7);
4140 #else
4141                 EnableItem(m, 7);
4142 #endif
4143         }
4144
4145
4146         /* Edit menu */
4147         m = GetMenuHandle(130);
4148
4149         /* Get menu size */
4150 #if TARGET_API_MAC_CARBON
4151         n = CountMenuItems(m);
4152 #else
4153         n = CountMItems(m);
4154 #endif
4155
4156         /* Reset menu */
4157         for (i = 1; i <= n; i++)
4158         {
4159                 /* Reset */
4160 #if TARGET_API_MAC_CARBON
4161                 DisableMenuItem(m, i);
4162                 CheckMenuItem(m, i, FALSE);
4163 #else
4164                 DisableItem(m, i);
4165                 CheckItem(m, i, FALSE);
4166 #endif
4167         }
4168
4169         /* Enable "edit" options if "needed" */
4170         if (!td)
4171         {
4172 #if TARGET_API_MAC_CARBON
4173                 EnableMenuItem(m, 1);
4174                 EnableMenuItem(m, 3);
4175                 EnableMenuItem(m, 4);
4176                 EnableMenuItem(m, 5);
4177                 EnableMenuItem(m, 6);
4178 #else
4179                 EnableItem(m, 1);
4180                 EnableItem(m, 3);
4181                 EnableItem(m, 4);
4182                 EnableItem(m, 5);
4183                 EnableItem(m, 6);
4184 #endif
4185         }
4186
4187
4188         /* Font menu */
4189         m = GetMenuHandle(131);
4190
4191         /* Get menu size */
4192 #if TARGET_API_MAC_CARBON
4193         n = CountMenuItems(m);
4194 #else
4195         n = CountMItems(m);
4196 #endif
4197
4198         /* Reset menu */
4199         for (i = 1; i <= n; i++)
4200         {
4201                 /* Reset */
4202 #if TARGET_API_MAC_CARBON
4203                 DisableMenuItem(m, i);
4204                 CheckMenuItem(m, i, FALSE);
4205 #else
4206                 DisableItem(m, i);
4207                 CheckItem(m, i, FALSE);
4208 #endif
4209         }
4210
4211         /* Hack -- look cute XXX XXX */
4212         /* SetItemStyle(m, 1, bold); */
4213
4214         /* Hack -- look cute XXX XXX */
4215         /* SetItemStyle(m, 2, extend); */
4216
4217         /* Active window */
4218         if (td)
4219         {
4220 #if TARGET_API_MAC_CARBON
4221                 /* Enable "bold" */
4222                 EnableMenuItem(m, 1);
4223
4224                 /* Enable "extend" */
4225                 EnableMenuItem(m, 2);
4226
4227                 /* Check the appropriate "bold-ness" */
4228                 if (td->font_face & bold) CheckMenuItem(m, 1, TRUE);
4229
4230                 /* Check the appropriate "wide-ness" */
4231                 if (td->font_face & extend) CheckMenuItem(m, 2, TRUE);
4232
4233                 /* Analyze fonts */
4234                 for (i = 4; i <= n; i++)
4235                 {
4236                         /* Enable it */
4237                         EnableMenuItem(m, i);
4238
4239                         /* Analyze font */
4240                         GetMenuItemText(m, i, s);
4241                         GetFNum(s, &value);
4242
4243                         /* Check active font */
4244                         if (td->font_id == value) CheckMenuItem(m, i, TRUE);
4245                 }
4246 #else
4247                 /* Enable "bold" */
4248                 EnableItem(m, 1);
4249
4250                 /* Enable "extend" */
4251                 EnableItem(m, 2);
4252
4253                 /* Check the appropriate "bold-ness" */
4254                 if (td->font_face & bold) CheckItem(m, 1, TRUE);
4255
4256                 /* Check the appropriate "wide-ness" */
4257                 if (td->font_face & extend) CheckItem(m, 2, TRUE);
4258
4259                 /* Analyze fonts */
4260                 for (i = 4; i <= n; i++)
4261                 {
4262                         /* Enable it */
4263                         EnableItem(m, i);
4264
4265                         /* Analyze font */
4266                         GetMenuItemText(m, i, s);
4267                         GetFNum(s, &value);
4268
4269                         /* Check active font */
4270                         if (td->font_id == value) CheckItem(m, i, TRUE);
4271                 }
4272 #endif
4273         }
4274
4275
4276         /* Size menu */
4277         m = GetMenuHandle(132);
4278
4279         /* Get menu size */
4280 #if TARGET_API_MAC_CARBON
4281         n = CountMenuItems(m);
4282 #else
4283         n = CountMItems(m);
4284 #endif
4285
4286         /* Reset menu */
4287         for (i = 1; i <= n; i++)
4288         {
4289                 /* Reset */
4290 #if TARGET_API_MAC_CARBON
4291                 DisableMenuItem(m, i);
4292                 CheckMenuItem(m, i, FALSE);
4293 #else
4294                 DisableItem(m, i);
4295                 CheckItem(m, i, FALSE);
4296 #endif
4297         }
4298         
4299         /* Active window */
4300         if (td)
4301         {
4302                 /* Analyze sizes */
4303                 for (i = 1; i <= n; i++)
4304                 {
4305 #if TARGET_API_MAC_CARBON
4306                         /* Analyze size */
4307                         GetMenuItemText(m, i, s);
4308                         s[s[0]+1] = '\0';
4309                         value = atoi((char*)(s+1));
4310
4311                         /* Enable the "real" sizes */
4312                         if (RealFont(td->font_id, value)) EnableMenuItem(m, i);
4313
4314                         /* Check the current size */
4315                         if (td->font_size == value) CheckMenuItem(m, i, TRUE);
4316 #else
4317                         /* Analyze size */
4318                         GetMenuItemText(m, i, s);
4319                         s[s[0]+1] = '\0';
4320                         value = atoi((char*)(s+1));
4321
4322                         /* Enable the "real" sizes */
4323                         if (RealFont(td->font_id, value)) EnableItem(m, i);
4324
4325                         /* Check the current size */
4326                         if (td->font_size == value) CheckItem(m, i, TRUE);
4327 #endif
4328                 }
4329         }
4330
4331
4332         /* Windows menu */
4333         m = GetMenuHandle(133);
4334
4335         /* Get menu size */
4336 #if TARGET_API_MAC_CARBON
4337         n = CountMenuItems(m);
4338 #else
4339         n = CountMItems(m);
4340 #endif
4341
4342         /* Check active windows */
4343         for (i = 1; i <= n; i++)
4344         {
4345                 /* Check if needed */
4346 #if TARGET_API_MAC_CARBON
4347                 CheckMenuItem(m, i, data[i-1].mapped);
4348 #else
4349                 CheckItem(m, i, data[i-1].mapped);
4350 #endif
4351         }
4352
4353
4354         /* Special menu */
4355         m = GetMenuHandle(134);
4356
4357         /* Get menu size */
4358 #if TARGET_API_MAC_CARBON
4359         n = CountMenuItems(m);
4360 #else
4361         n = CountMItems(m);
4362 #endif
4363
4364         /* Reset menu */
4365         for (i = 1; i <= n; i++)
4366         {
4367                 /* Reset */
4368 #if TARGET_API_MAC_CARBON
4369                 DisableMenuItem(m, i);
4370                 CheckMenuItem(m, i, FALSE);
4371 #else
4372                 DisableItem(m, i);
4373                 CheckItem(m, i, FALSE);
4374 #endif
4375         }
4376
4377 #if TARGET_API_MAC_CARBON
4378         /* Item "arg_sound" */
4379         EnableMenuItem(m, 1);
4380         CheckMenuItem(m, 1, arg_sound);
4381
4382         /* Item "arg_graphics" */
4383         EnableMenuItem(m, 2);
4384         CheckMenuItem(m, 2, arg_graphics);
4385
4386         /* Item "arg_fiddle" */
4387         EnableMenuItem(m, 4);
4388         CheckMenuItem(m, 4, arg_fiddle);
4389
4390         /* Item "arg_wizard" */
4391         EnableMenuItem(m, 5);
4392         CheckMenuItem(m, 5, arg_wizard);
4393
4394         /* Item "SoundSetting" */
4395         EnableMenuItem(m, 7);
4396
4397         /* Item NewStyle Graphics */
4398         EnableMenuItem(m, 8);
4399         CheckMenuItem(m, 8, use_newstyle_graphics);
4400
4401         /* Item Bigtile Mode */
4402         EnableMenuItem(m, 9);
4403         CheckMenuItem(m, 9, arg_bigtile);
4404 #else
4405         /* Item "arg_sound" */
4406         EnableItem(m, 1);
4407         CheckItem(m, 1, arg_sound);
4408
4409         /* Item "arg_graphics" */
4410         EnableItem(m, 2);
4411         CheckItem(m, 2, arg_graphics);
4412
4413         /* Item "arg_fiddle" */
4414         EnableItem(m, 4);
4415         CheckItem(m, 4, arg_fiddle);
4416
4417         /* Item "arg_wizard" */
4418         EnableItem(m, 5);
4419         CheckItem(m, 5, arg_wizard);
4420
4421         /* Item "SoundSetting" */
4422         EnableItem(m, 7);
4423
4424         /* Item NewStyle Graphics */
4425         EnableItem(m, 8);
4426         CheckItem(m, 8, use_newstyle_graphics);
4427
4428         /* Item Bigtile Mode */
4429         EnableItem(m, 9);
4430         CheckItem(m, 9, arg_bigtile);
4431 #endif
4432
4433         /* TileWidth menu */
4434         m = GetMenuHandle(135);
4435
4436         /* Get menu size */
4437 #if TARGET_API_MAC_CARBON
4438         n = CountMenuItems(m);
4439 #else
4440         n = CountMItems(m);
4441 #endif
4442
4443         /* Reset menu */
4444         for (i = 1; i <= n; i++)
4445         {
4446                 /* Reset */
4447 #if TARGET_API_MAC_CARBON
4448                 DisableMenuItem(m, i);
4449                 CheckMenuItem(m, i, FALSE);
4450 #else
4451                 DisableItem(m, i);
4452                 CheckItem(m, i, FALSE);
4453 #endif
4454         }
4455
4456         /* Active window */
4457         if (td)
4458         {
4459                 /* Analyze sizes */
4460                 for (i = 1; i <= n; i++)
4461                 {
4462                         /* Analyze size */
4463                         /* GetMenuItemText(m,i,s); */
4464                         GetMenuItemText(m, i, s);
4465                         s[s[0]+1] = '\0';
4466                         value = atoi((char*)(s+1));
4467
4468 #if TARGET_API_MAC_CARBON
4469                         /* Enable */
4470                         EnableMenuItem(m, i);
4471
4472                         /* Check the current size */
4473                         if (td->tile_wid == value) CheckMenuItem(m, i, TRUE);
4474 #else
4475                         /* Enable */
4476                         EnableItem(m, i);
4477
4478                         /* Check the current size */
4479                         if (td->tile_wid == value) CheckItem(m, i, TRUE);
4480 #endif
4481                 }
4482         }
4483
4484
4485         /* TileHeight menu */
4486         m = GetMenuHandle(136);
4487
4488         /* Get menu size */
4489 #if TARGET_API_MAC_CARBON
4490         n = CountMenuItems(m);
4491 #else
4492         n = CountMItems(m);
4493 #endif
4494
4495         /* Reset menu */
4496         for (i = 1; i <= n; i++)
4497         {
4498                 /* Reset */
4499 #if TARGET_API_MAC_CARBON
4500                 DisableMenuItem(m, i);
4501                 CheckMenuItem(m, i, FALSE);
4502 #else
4503                 DisableItem(m, i);
4504                 CheckItem(m, i, FALSE);
4505 #endif
4506         }
4507
4508         /* Active window */
4509         if (td)
4510         {
4511                 /* Analyze sizes */
4512                 for (i = 1; i <= n; i++)
4513                 {
4514                         /* Analyze size */
4515                         GetMenuItemText(m, i, s);
4516                         s[s[0]+1] = '\0';
4517                         value = atoi((char*)(s+1));
4518
4519 #if TARGET_API_MAC_CARBON
4520                         /* Enable */
4521                         EnableMenuItem(m, i);
4522
4523                         /* Check the current size */
4524                         if (td->tile_hgt == value) CheckMenuItem(m, i, TRUE);
4525 #else
4526                         /* Enable */
4527                         EnableItem(m, i);
4528
4529                         /* Check the current size */
4530                         if (td->tile_hgt == value) CheckItem(m, i, TRUE);
4531 #endif
4532                 }
4533         }
4534 }
4535
4536
4537 /*
4538  * Process a menu selection (see above)
4539  *
4540  * Hack -- assume that invalid menu selections are disabled above,
4541  * which I have been informed may not be reliable.  XXX XXX XXX
4542  */
4543 static void menu(long mc)
4544 {
4545         int i;
4546
4547         int menuid, selection;
4548
4549         static unsigned char s[1000];
4550
4551         short fid;
4552
4553         term_data *td = NULL;
4554
4555         WindowPtr old_win;
4556
4557
4558         /* Analyze the menu command */
4559         menuid = HiWord(mc);
4560         selection = LoWord(mc);
4561
4562
4563         /* Find the window */
4564         for (i = 0; i < MAX_TERM_DATA; i++)
4565         {
4566                 /* Skip dead windows */
4567                 if (!data[i].t) continue;
4568
4569                 /* Notice matches */
4570                 if (data[i].w == FrontWindow()) td = &data[i];
4571         }
4572
4573
4574         /* Branch on the menu */
4575         switch (menuid)
4576         {
4577                 /* Apple Menu */
4578                 case 128:
4579                 {
4580                         /* About Angband... */
4581 #if TARGET_API_MAC_CARBON
4582                         if (selection == 1)
4583                         {
4584                                 DialogPtr dialog;
4585                                 short item_hit;
4586
4587                                 /* Get the about dialogue */
4588                                 dialog=GetNewDialog(128, 0, (WindowPtr)-1);
4589
4590                                 /* Move it to the middle of the screen */
4591                                 RepositionWindow(
4592                                         GetDialogWindow(dialog),
4593                                         NULL,
4594                                         kWindowCenterOnMainScreen);
4595
4596                                 /* Show the dialog */
4597                                 TransitionWindow(GetDialogWindow(dialog),
4598                                         kWindowZoomTransitionEffect,
4599                                         kWindowShowTransitionAction,
4600                                         NULL);
4601
4602                                 /* Wait for user to click on it */
4603                                 ModalDialog(0, &item_hit);
4604
4605                                 /* Free the dialogue */
4606                                 DisposeDialog(dialog);
4607                                 break;
4608                         }
4609 #else
4610                         if (selection == 1)
4611                         {
4612                                 DialogPtr dialog;
4613                                 Rect r;
4614                                 short item_hit;
4615
4616                                 dialog=GetNewDialog(128, 0, (WindowPtr)-1);
4617
4618                                 r=dialog->portRect;
4619                                 center_rect(&r, &qd.screenBits.bounds);
4620                                 MoveWindow(dialog, r.left, r.top, 1);
4621                                 ShowWindow(dialog);
4622                                 ModalDialog(0, &item_hit);
4623                                 DisposeDialog(dialog);
4624                                 break;
4625                         }
4626
4627                         /* Desk accessory */
4628                         /* GetMenuItemText(GetMHandle(128),selection,s); */
4629                         GetMenuItemText(GetMenuHandle(128), selection, s);
4630                         OpenDeskAcc(s);
4631                         break;
4632 #endif
4633                 }
4634
4635                 /* File Menu */
4636                 case 129:
4637                 {
4638                         switch (selection)
4639                         {
4640                                 /* New */
4641                                 case 1:
4642                                 {
4643                                         do_menu_file_new();
4644                                         break;
4645                                 }
4646
4647                                 /* Open... */
4648                                 case 2:
4649                                 {
4650                                         do_menu_file_open(FALSE);
4651                                         break;
4652                                 }
4653
4654                                 /* Import... */
4655                                 case 3:
4656                                 {
4657                                         do_menu_file_open(TRUE);
4658                                         break;
4659                                 }
4660
4661                                 /* Close */
4662                                 case 4:
4663                                 {
4664                                         /* No window */
4665                                         if (!td) break;
4666
4667                                         /* Not Mapped */
4668                                         td->mapped = FALSE;
4669
4670                                         /* Not Mapped */
4671                                         td->t->mapped_flag = FALSE;
4672
4673                                         /* Hide the window */
4674                                         HideWindow(td->w);
4675
4676                                         break;
4677                                 }
4678
4679                                 /* Save */
4680                                 case 5:
4681                                 {
4682                                         if (!can_save){
4683 #ifdef JP
4684                                                 plog("º£¤Ï¥»¡¼¥Ö¤¹¤ë¤³¤È¤Ï½ÐÍè¤Þ¤»¤ó¡£");
4685 #else
4686                                                 plog("You may not do that right now.");
4687 #endif
4688                                                 break;
4689                                         }
4690                                         
4691                                         /* Hack -- Forget messages */
4692                                         msg_flag = FALSE;
4693
4694                                         /* Hack -- Save the game */
4695                                         do_cmd_save_game(FALSE);
4696
4697                                         break;
4698                                 }
4699
4700                                 /* Quit (with save) */
4701                                 case 7:
4702                                 {
4703                                         /* Save the game (if necessary) */
4704                                         if (game_in_progress && character_generated)
4705                                         {
4706                                                 if (!can_save){
4707 #ifdef JP
4708                                                         plog("º£¤Ï¥»¡¼¥Ö¤¹¤ë¤³¤È¤Ï½ÐÍè¤Þ¤»¤ó¡£");
4709 #else
4710                                                         plog("You may not do that right now.");
4711 #endif
4712                                                         break;
4713                                                 }
4714                                                 /* Hack -- Forget messages */
4715                                                 msg_flag = FALSE;
4716
4717                                                 /* Save the game */
4718 #if 0
4719                                                 do_cmd_save_game(FALSE);
4720 #endif
4721                                                 Term_key_push(SPECIAL_KEY_QUIT);
4722                                                 break;
4723                                         }
4724
4725                                         /* Quit */
4726                                         quit(NULL);
4727                                         break;
4728                                 }
4729                         }
4730                         break;
4731                 }
4732
4733                 /* Edit menu */
4734                 case 130:
4735                 {
4736                         /* Unused */
4737                         break;
4738                 }
4739
4740                 /* Font menu */
4741                 case 131:
4742                 {
4743                         /* Require a window */
4744                         if (!td) break;
4745
4746                         /* Memorize old */
4747                         old_win = active;
4748
4749                         /* Activate */
4750                         activate(td->w);
4751
4752                         /* Toggle the "bold" setting */
4753                         if (selection == 1)
4754                         {
4755                                 /* Toggle the setting */
4756                                 if (td->font_face & bold)
4757                                 {
4758                                         td->font_face &= ~bold;
4759                                 }
4760                                 else
4761                                 {
4762                                         td->font_face |= bold;
4763                                 }
4764
4765                                 /* Tile Width Hight Init */
4766                                 td->tile_wid = td->tile_hgt = 0;
4767
4768                                 /* Apply and Verify */
4769                                 term_data_check_font(td);
4770                                 term_data_check_size(td);
4771
4772                                 /* Resize and Redraw */
4773                                 term_data_resize(td);
4774                                 term_data_redraw(td);
4775
4776                                 break;
4777                         }
4778
4779                         /* Toggle the "wide" setting */
4780                         if (selection == 2)
4781                         {
4782                                 /* Toggle the setting */
4783                                 if (td->font_face & extend)
4784                                 {
4785                                         td->font_face &= ~extend;
4786                                 }
4787                                 else
4788                                 {
4789                                         td->font_face |= extend;
4790                                 }
4791
4792                                 /* Tile Width Hight Init */
4793                                 td->tile_wid = td->tile_hgt = 0;
4794
4795                                 /* Apply and Verify */
4796                                 term_data_check_font(td);
4797                                 term_data_check_size(td);
4798
4799                                 /* Resize and Redraw */
4800                                 term_data_resize(td);
4801                                 term_data_redraw(td);
4802
4803                                 break;
4804                         }
4805
4806                         /* Get a new font name */
4807                         GetMenuItemText(GetMenuHandle(131), selection, s);
4808                         GetFNum(s, &fid);
4809
4810                         /* Save the new font id */
4811                         td->font_id = fid;
4812
4813                         /* Current size is bad for new font */
4814                         if (!RealFont(td->font_id, td->font_size))
4815                         {
4816                                 /* Find similar size */
4817                                 for (i = 1; i <= 32; i++)
4818                                 {
4819                                         /* Adjust smaller */
4820                                         if (td->font_size - i >= 8)
4821                                         {
4822                                                 if (RealFont(td->font_id, td->font_size - i))
4823                                                 {
4824                                                         td->font_size -= i;
4825                                                         break;
4826                                                 }
4827                                         }
4828
4829                                         /* Adjust larger */
4830                                         if (td->font_size + i <= 128)
4831                                         {
4832                                                 if (RealFont(td->font_id, td->font_size + i))
4833                                                 {
4834                                                         td->font_size += i;
4835                                                         break;
4836                                                 }
4837                                         }
4838                                 }
4839                         }
4840
4841                         /* Tile Width Hight Init */
4842                         td->tile_wid = td->tile_hgt = 0;
4843
4844                         /* Apply and Verify */
4845                         term_data_check_font(td);
4846                         term_data_check_size(td);
4847
4848                         /* Resize and Redraw */
4849                         term_data_resize(td);
4850                         term_data_redraw(td);
4851
4852                         /* Restore the window */
4853                         activate(old_win);
4854
4855                         break;
4856                 }
4857
4858                 /* Size menu */
4859                 case 132:
4860                 {
4861                         if (!td) break;
4862
4863                         /* Save old */
4864                         old_win = active;
4865
4866                         /* Activate */
4867                         activate(td->w);
4868
4869                         GetMenuItemText(GetMenuHandle(132), selection, s);
4870                         s[s[0]+1]=0;
4871                         td->font_size = atoi((char*)(s+1));
4872
4873                         /* Tile Width Hight Init */
4874                         td->tile_wid = td->tile_hgt = 0;
4875
4876                         /* Apply and Verify */
4877                         term_data_check_font(td);
4878                         term_data_check_size(td);
4879
4880                         /* Resize and Redraw */
4881                         term_data_resize(td);
4882                         term_data_redraw(td);
4883
4884                         /* Restore */
4885                         activate(old_win);
4886
4887                         break;
4888                 }
4889
4890                 /* Window menu */
4891                 case 133:
4892                 {
4893                         /* Parse */
4894                         i = selection - 1;
4895
4896                         /* Check legality of choice */
4897                         if ((i < 0) || (i >= MAX_TERM_DATA)) break;
4898
4899                         /* Obtain the window */
4900                         td = &data[i];
4901
4902                         /* Mapped */
4903                         td->mapped = TRUE;
4904
4905                         /* Link */      
4906                         term_data_link(i);
4907
4908                         /* Mapped (?) */
4909                         td->t->mapped_flag = TRUE;
4910
4911                         /* Show the window */
4912                         ShowWindow(td->w);
4913
4914                         /* Bring to the front */
4915                         SelectWindow(td->w);
4916
4917                         break;
4918                 }
4919
4920                 /* Special menu */
4921                 case 134:
4922                 {
4923                         switch (selection)
4924                         {
4925                                 case 1:
4926                                 {
4927                                         /* Toggle arg_sound */
4928                                         arg_sound = !arg_sound;
4929
4930                                         /* React to changes */
4931                                         Term_xtra(TERM_XTRA_REACT, 0);
4932
4933                                         break;
4934                                 }
4935
4936                                 case 2:
4937                                 {
4938                                         /* Toggle arg_graphics */
4939                                         arg_graphics = !arg_graphics;
4940                                         if( arg_graphics == true ){
4941                                                 ANGBAND_GRAF = "old";
4942                                                 arg_newstyle_graphics = false;
4943                                                 grafWidth = grafHeight = 8;
4944                                                 pictID = 1001;
4945                                         }
4946
4947                                         /* Hack -- Force redraw */
4948                                         Term_key_push(KTRL('R'));
4949
4950                                         break;
4951                                 }
4952
4953                                 case 4:
4954                                 {
4955                                         arg_fiddle = !arg_fiddle;
4956                                         break;
4957                                 }
4958
4959                                 case 5:
4960                                 {
4961                                         arg_wizard = !arg_wizard;
4962                                         break;
4963                                 }
4964
4965                                 case 7:
4966                                 {
4967                                         SoundConfigDLog();
4968                                         break;
4969                                 }
4970                                 case 8:
4971                                 {
4972                                         if (streq(ANGBAND_GRAF, "old"))
4973                                         {
4974                                                 ANGBAND_GRAF = "new";
4975                                                 arg_newstyle_graphics = true;
4976                                                 grafWidth = grafHeight = 16;
4977                                                 pictID = 1002;
4978                                         }
4979                                         else
4980                                         {
4981                                                 ANGBAND_GRAF = "old";
4982                                                 arg_newstyle_graphics = false;
4983                                                 grafWidth = grafHeight = 8;
4984                                                 pictID = 1001;
4985                                         }
4986
4987                                         /* Hack -- Force redraw */
4988                                         Term_key_push(KTRL('R'));
4989                                         break;
4990                                 }
4991
4992                                 case 9: /* bigtile mode */
4993                                 {
4994                                         term_data *td = &data[0];
4995
4996                                         if (!can_save){
4997 #ifdef JP
4998                                                 plog("º£¤ÏÊѹ¹½ÐÍè¤Þ¤»¤ó¡£");
4999 #else
5000                                                 plog("You may not do that right now.");
5001 #endif
5002                                                 break;
5003                                         }
5004
5005                                         /* Toggle "arg_bigtile" */
5006                                         arg_bigtile = !arg_bigtile;
5007
5008                                         /* Activate */
5009                                         Term_activate(td->t);
5010
5011                                         /* Resize the term */
5012                                         Term_resize(td->cols, td->rows);
5013
5014                                         break;
5015                                 }
5016
5017                         }
5018
5019                         break;
5020                 }
5021
5022                 /* TileWidth menu */
5023                 case 135:
5024                 {
5025                         if (!td) break;
5026
5027                         /* Save old */
5028                         old_win = active;
5029
5030                         /* Activate */
5031                         activate(td->w);
5032
5033                         GetMenuItemText(GetMenuHandle(135), selection, s);
5034                         s[s[0]+1]=0;
5035                         td->tile_wid = atoi((char*)(s+1));
5036
5037                         /* Apply and Verify */
5038                         term_data_check_size(td);
5039
5040                         /* Resize and Redraw */
5041                         term_data_resize(td);
5042                         term_data_redraw(td);
5043
5044                         /* Restore */
5045                         activate(old_win);
5046
5047                         break;
5048                 }
5049
5050                 /* TileHeight menu */
5051                 case 136:
5052                 {
5053                         if (!td) break;
5054
5055                         /* Save old */
5056                         old_win = active;
5057
5058                         /* Activate */
5059                         activate(td->w);
5060
5061                         GetMenuItemText(GetMenuHandle(136), selection, s);
5062                         s[s[0]+1]=0;
5063                         td->tile_hgt = atoi((char*)(s+1));
5064
5065                         /* Apply and Verify */
5066                         term_data_check_size(td);
5067
5068                         /* Resize and Redraw */
5069                         term_data_resize(td);
5070                         term_data_redraw(td);
5071
5072                         /* Restore */
5073                         activate(old_win);
5074
5075                         break;
5076                 }
5077         }
5078
5079
5080         /* Clean the menu */
5081         HiliteMenu(0);
5082 }
5083
5084
5085 #ifdef USE_SFL_CODE
5086
5087
5088 /*
5089  * Check for extra required parameters -- From "Maarten Hazewinkel"
5090  */
5091 static OSErr CheckRequiredAEParams(const AppleEvent *theAppleEvent)
5092 {
5093         OSErr   aeError;
5094         DescType        returnedType;
5095         Size    actualSize;
5096
5097         aeError = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard,
5098                                     &returnedType, NULL, 0, &actualSize);
5099
5100         if (aeError == errAEDescNotFound) return (noErr);
5101
5102         if (aeError == noErr) return (errAEParamMissed);
5103
5104         return (aeError);
5105 }
5106
5107
5108 /*
5109  * Apple Event Handler -- Open Application
5110  */
5111 static pascal OSErr AEH_Start(const AppleEvent *theAppleEvent,
5112                               AppleEvent *reply, long handlerRefCon)
5113 {
5114 #pragma unused(reply, handlerRefCon)
5115
5116         return (CheckRequiredAEParams(theAppleEvent));
5117 }
5118
5119
5120 /*
5121  * Apple Event Handler -- Quit Application
5122  */
5123 static pascal OSErr AEH_Quit(const AppleEvent *theAppleEvent,
5124                              AppleEvent *reply, long handlerRefCon)
5125 {
5126 #pragma unused(reply, handlerRefCon)
5127 #if TARGET_API_MAC_CARBON
5128
5129         /* Save the game (if necessary) */
5130         if (game_in_progress && character_generated)
5131         {
5132                         if (!can_save){
5133 #ifdef JP
5134                                 plog("º£¤Ï¥»¡¼¥Ö¤¹¤ë¤³¤È¤Ï½ÐÍè¤Þ¤»¤ó¡£");
5135 #else
5136                                 plog("You may not do that right now.");
5137 #endif
5138                                 return;
5139                         }
5140                         /* Hack -- Forget messages */
5141                         msg_flag = FALSE;
5142
5143                         /* Save the game */
5144 #if 0
5145                         do_cmd_save_game(FALSE);
5146 #endif
5147                         Term_key_push(SPECIAL_KEY_QUIT);
5148                         return;
5149                 }
5150
5151                 /* Quit */
5152                 quit(NULL);
5153 #else
5154         /* Quit later */
5155         quit_when_ready = TRUE;
5156
5157         /* Check arguments */
5158         return (CheckRequiredAEParams(theAppleEvent));
5159 #endif
5160 }
5161
5162
5163 /*
5164  * Apple Event Handler -- Print Documents
5165  */
5166 static pascal OSErr AEH_Print(const AppleEvent *theAppleEvent,
5167                               AppleEvent *reply, long handlerRefCon)
5168 {
5169 #pragma unused(theAppleEvent, reply, handlerRefCon)
5170
5171         return (errAEEventNotHandled);
5172 }
5173
5174
5175 /*
5176  * Apple Event Handler by Steve Linberg (slinberg@crocker.com).
5177  *
5178  * The old method of opening savefiles from the finder does not work
5179  * on the Power Macintosh, because CountAppFiles and GetAppFiles,
5180  * used to return information about the selected document files when
5181  * an application is launched, are part of the Segment Loader, which
5182  * is not present in the RISC OS due to the new memory architecture.
5183  *
5184  * The "correct" way to do this is with AppleEvents.  The following
5185  * code is modeled on the "Getting Files Selected from the Finder"
5186  * snippet from Think Reference 2.0.  (The prior sentence could read
5187  * "shamelessly swiped & hacked")
5188  */
5189 static pascal OSErr AEH_Open(const AppleEvent *theAppleEvent,
5190                              AppleEvent* reply, long handlerRefCon)
5191 {
5192 #pragma unused(reply, handlerRefCon)
5193
5194         FSSpec          myFSS;
5195         AEDescList      docList;
5196         OSErr           err;
5197         Size            actualSize;
5198         AEKeyword       keywd;
5199         DescType        returnedType;
5200         char            foo[128];
5201         FInfo           myFileInfo;
5202
5203         /* Put the direct parameter (a descriptor list) into a docList */
5204         err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &docList);
5205         if (err) return err;
5206
5207         /*
5208          * We ignore the validity check, because we trust the FInder, and we only
5209          * allow one savefile to be opened, so we ignore the depth of the list.
5210          */
5211
5212         err = AEGetNthPtr(&docList, 1L, typeFSS, &keywd,
5213                           &returnedType, (Ptr) &myFSS, sizeof(myFSS), &actualSize);
5214         if (err) return err;
5215
5216         /* Only needed to check savefile type below */
5217         err = FSpGetFInfo(&myFSS, &myFileInfo);
5218         if (err)
5219         {
5220                 sprintf(foo, "Arg!  FSpGetFInfo failed with code %d", err);
5221                 mac_warning (foo);
5222                 return err;
5223         }
5224
5225         /* Ignore non 'SAVE' files */
5226         if (myFileInfo.fdType != 'SAVE') return noErr;
5227
5228         /* XXX XXX XXX Extract a file name */
5229         PathNameFromDirID(myFSS.parID, myFSS.vRefNum, (StringPtr)savefile);
5230         pstrcat((StringPtr)savefile, (StringPtr)&myFSS.name);
5231
5232         /* Convert the string */
5233         ptocstr((StringPtr)savefile);
5234
5235         /* Delay actual open */
5236         open_when_ready = TRUE;
5237
5238         /* Dispose */
5239         err = AEDisposeDesc(&docList);
5240
5241         /* Success */
5242         return noErr;
5243 }
5244
5245
5246 #endif
5247
5248
5249
5250 /*
5251  * Macintosh modifiers (event.modifier & ccc):
5252  *   cmdKey, optionKey, shiftKey, alphaLock, controlKey
5253  *
5254  *
5255  * Macintosh Keycodes (0-63 normal, 64-95 keypad, 96-127 extra):
5256  *
5257  * Return:36
5258  * Delete:51
5259  *
5260  * Period:65
5261  * Star:67
5262  * Plus:69
5263  * Clear:71
5264  * Slash:75
5265  * Enter:76
5266  * Minus:78
5267  * Equal:81
5268  * 0-7:82-89
5269  * 8-9:91-92
5270  *
5271  * F5: 96
5272  * F6: 97
5273  * F7: 98
5274  * F3:99
5275  * F8:100
5276  * F10:109
5277  * F11:103
5278  * F13:105
5279  * F14:107
5280  * F9:101
5281  * F12:111
5282  * F15:113
5283  * Help:114
5284  * Home:115
5285  * PgUp:116
5286  * Del:117
5287  * F4: 118
5288  * End:119
5289  * F2:120
5290  * PgDn:121
5291  * F1:122
5292  * Lt:123
5293  * Rt:124
5294  * Dn:125
5295  * Up:126
5296  */
5297
5298
5299 /*
5300  * Optimize non-blocking calls to "CheckEvents()"
5301  * Idea from "Maarten Hazewinkel <mmhazewi@cs.ruu.nl>"
5302  */
5303 #define EVENT_TICKS 6
5304
5305
5306 /*
5307  * Check for Events, return TRUE if we process any
5308  *
5309  * Hack -- Handle AppleEvents if appropriate (ignore result code).
5310  */
5311 static bool CheckEvents(bool wait)
5312 {
5313         EventRecord event;
5314
5315         WindowPtr w;
5316
5317         Rect r;
5318
5319         long newsize;
5320
5321         int ch, ck;
5322
5323         int mc, ms, mo, mx;
5324
5325         int i;
5326
5327         term_data *td = NULL;
5328
5329         huge curTicks;
5330
5331         static huge lastTicks = 0L;
5332
5333
5334         /* Access the clock */
5335         curTicks = TickCount();
5336
5337         /* Hack -- Allow efficient checking for non-pending events */
5338         if (!wait && (curTicks < lastTicks + EVENT_TICKS)) return (FALSE);
5339
5340         /* Timestamp last check */
5341         lastTicks = curTicks;
5342
5343 #if TARGET_API_MAC_CARBON
5344         WaitNextEvent( everyEvent, &event, 1L, nil );
5345 #else
5346         /* Let the "system" run */
5347         SystemTask();
5348
5349         /* Get an event (or null) */
5350         GetNextEvent(everyEvent, &event);
5351 #endif
5352
5353         /* Hack -- Nothing is ready yet */
5354         if (event.what == nullEvent) return (FALSE);
5355
5356         /* Analyze the event */
5357         switch (event.what)
5358         {
5359
5360 #if 0
5361
5362                 case activateEvt:
5363                 {
5364                         w = (WindowPtr)event.message;
5365
5366                         activate(w);
5367
5368                         break;
5369                 }
5370
5371 #endif
5372
5373                 case updateEvt:
5374                 {
5375                         /* Extract the window */
5376                         w = (WindowPtr)event.message;
5377
5378                         /* Find the window */
5379                         for (i = 0; i < MAX_TERM_DATA; i++)
5380                         {
5381                                 /* Skip dead windows */
5382                                 if (!data[i].t) continue;
5383
5384                                 /* Notice matches */
5385                                 if (data[i].w == w) td = &data[i];
5386                         }
5387
5388                         /* Hack XXX XXX XXX */
5389                         BeginUpdate(w);
5390                         EndUpdate(w);
5391
5392                         /* Redraw the window */
5393                         if (td) term_data_redraw(td);
5394
5395                         break;
5396                 }
5397
5398                 case keyDown:
5399                 case autoKey:
5400                 {
5401                         /* Extract some modifiers */
5402                         mc = (event.modifiers & controlKey) ? TRUE : FALSE;
5403                         ms = (event.modifiers & shiftKey) ? TRUE : FALSE;
5404                         mo = (event.modifiers & optionKey) ? TRUE : FALSE;
5405                         mx = (event.modifiers & cmdKey) ? TRUE : FALSE;
5406
5407                         /* Keypress: (only "valid" if ck < 96) */
5408                         ch = (event.message & charCodeMask) & 255;
5409
5410                         /* Keycode: see table above */
5411                         ck = ((event.message & keyCodeMask) >> 8) & 255;
5412
5413                         /* Command + "normal key" -> menu action */
5414                         if (mx && (ck < 64))
5415                         {
5416                                 /* Hack -- Prepare the menus */
5417                                 setup_menus();
5418
5419                                 /* Run the Menu-Handler */
5420                                 menu(MenuKey(ch));
5421
5422                                 /* Turn off the menus */
5423                                 HiliteMenu(0);
5424
5425                                 /* Done */
5426                                 break;
5427                         }
5428
5429
5430                         /* Hide the mouse pointer */
5431                         ObscureCursor();
5432
5433                         /* Normal key -> simple keypress */
5434                         if (ck < 64)
5435                         {
5436                                 /* Enqueue the keypress */
5437                                 Term_keypress(ch);
5438                         }
5439
5440                         /* Bizarre key -> encoded keypress */
5441                         else if (ck <= 127)
5442                         {
5443                                 /* Hack -- introduce with control-underscore */
5444                                 Term_keypress(31);
5445
5446                                 /* Send some modifier keys */
5447                                 if (mc) Term_keypress('C');
5448                                 if (ms) Term_keypress('S');
5449                                 if (mo) Term_keypress('O');
5450                                 if (mx) Term_keypress('X');
5451
5452                                 /* Hack -- Downshift and encode the keycode */
5453                                 Term_keypress('0' + (ck - 64) / 10);
5454                                 Term_keypress('0' + (ck - 64) % 10);
5455
5456                                 /* Hack -- Terminate the sequence */
5457                                 /* MPW can generate 10 or 13 for keycode of '\r' */
5458                                 /* -noMapCR option swaps '\r' and '\n' */
5459                                 Term_keypress('\r');
5460                         }
5461
5462                         break;
5463                 }
5464
5465                 case mouseDown:
5466                 {
5467                         int code;
5468
5469                         /* Analyze click location */
5470                         code = FindWindow(event.where, &w);
5471
5472                         /* Find the window */
5473                         for (i = 0; i < MAX_TERM_DATA; i++)
5474                         {
5475                                 /* Skip dead windows */
5476                                 if (!data[i].t) continue;
5477
5478                                 /* Notice matches */
5479                                 if (data[i].w == w) td = &data[i];
5480                         }
5481
5482                         /* Analyze */
5483                         switch (code)
5484                         {
5485                                 case inMenuBar:
5486                                 {
5487                                         setup_menus();
5488                                         menu(MenuSelect(event.where));
5489                                         HiliteMenu(0);
5490                                         break;
5491                                 }
5492 #if !TARGET_API_MAC_CARBON
5493                                 case inSysWindow:
5494                                 {
5495                                         SystemClick(&event, w);
5496                                         break;
5497                                 }
5498 #endif
5499
5500                                 case inDrag:
5501                                 {
5502                                         Point p;
5503
5504                                         WindowPtr old_win;
5505                                         BitMap screen;
5506                                         Rect portRect;
5507 #if TARGET_API_MAC_CARBON                                               
5508                                         GetQDGlobalsScreenBits( &screen );
5509 #else
5510                                         screen = qd.screenBits;
5511 #endif  
5512                                         r = screen.bounds;
5513                                         r.top += 20; /* GetMBarHeight() XXX XXX XXX */
5514                                         InsetRect(&r, 4, 4);
5515                                         DragWindow(w, event.where, &r);
5516
5517                                         /* Oops */
5518                                         if (!td) break;
5519
5520                                         /* Save */
5521                                         old_win = active;
5522
5523                                         /* Activate */
5524                                         activate(td->w);
5525
5526                                         /* Analyze */
5527 #if TARGET_API_MAC_CARBON
5528                                         GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &portRect );
5529 #else
5530                                         portRect = td->w->portRect;
5531                                         local_to_global( &portRect );
5532 #endif
5533                                         p.h = portRect.left;
5534                                         p.v = portRect.top;
5535 #if !TARGET_API_MAC_CARBON
5536                                         LocalToGlobal(&p);
5537 #endif
5538                                         td->r.left = p.h;
5539                                         td->r.top = p.v;
5540
5541                                         /* Restore */
5542                                         activate(old_win);
5543
5544                                         /* Apply and Verify */
5545                                         term_data_check_size(td);
5546
5547                                         break;
5548                                 }
5549
5550                                 case inGoAway:
5551                                 {
5552                                         /* Oops */
5553                                         if (!td) break;
5554
5555                                         /* Track the go-away box */
5556                                         if (TrackGoAway(w, event.where))
5557                                         {
5558                                                 /* Not Mapped */
5559                                                 td->mapped = FALSE;
5560
5561                                                 /* Not Mapped */
5562                                                 td->t->mapped_flag = FALSE;
5563
5564                                                 /* Hide the window */
5565                                                 HideWindow(td->w);
5566                                         }
5567
5568                                         break;
5569                                 }
5570
5571                                 case inGrow:
5572                                 {
5573                                         s16b x, y;
5574
5575                                         term *old = Term;
5576                                         BitMap          screen;
5577         
5578 #if TARGET_API_MAC_CARBON
5579                                         GetQDGlobalsScreenBits( &screen );
5580 #else
5581                                         screen = qd.screenBits;
5582 #endif
5583                                         /* Oops */
5584                                         if (!td) break;
5585
5586                                         /* Fake rectangle */
5587                                         r.left = 20 * td->tile_wid + td->size_ow1;
5588                                         r.right = screen.bounds.right;
5589                                         r.top = 1 * td->tile_hgt + td->size_oh1;
5590                                         r.bottom = screen.bounds.bottom;
5591
5592                                         /* Grow the rectangle */
5593                                         newsize = GrowWindow(w, event.where, &r);
5594
5595                                         /* Handle abort */
5596                                         if (!newsize) break;
5597
5598                                         /* Extract the new size in pixels */
5599                                         y = HiWord(newsize) - td->size_oh1 - td->size_oh2;
5600                                         x = LoWord(newsize) - td->size_ow1 - td->size_ow2;
5601
5602                                         /* Extract a "close" approximation */
5603                                         td->rows = y / td->tile_hgt;
5604                                         td->cols = x / td->tile_wid;
5605
5606                                         /* Apply and Verify */
5607                                         term_data_check_size(td);
5608                                         /* Activate */
5609                                         Term_activate(td->t);
5610
5611                                         /* Hack -- Resize the term */
5612                                         Term_resize(td->cols, td->rows);
5613
5614                                         /* Resize and Redraw */
5615                                         term_data_resize(td);
5616                                         term_data_redraw(td);
5617
5618                                         /* Restore */
5619                                         Term_activate(old);
5620
5621                                         break;
5622                                 }
5623
5624                                 case inContent:
5625                                 {
5626                                         SelectWindow(w);
5627
5628                                         break;
5629                                 }
5630                         }
5631
5632                         break;
5633                 }
5634
5635                 /* Disk Event -- From "Maarten Hazewinkel" */
5636                 case diskEvt:
5637                 {
5638
5639 #if TARGET_API_MAC_CARBON
5640 #else
5641                         /* check for error when mounting the disk */
5642                         if (HiWord(event.message) != noErr)
5643                         {
5644                                 Point p =
5645                                 {120, 120};
5646
5647                                 DILoad();
5648                                 DIBadMount(p, event.message);
5649                                 DIUnload();
5650                         }
5651 #endif
5652                         break;
5653                 }
5654
5655                 /* OS Event -- From "Maarten Hazewinkel" */
5656                 case osEvt:
5657                 {
5658                         switch ((event.message >> 24) & 0x000000FF)
5659                         {
5660                                 case suspendResumeMessage:
5661
5662                                 /* Resuming: activate the front window */
5663                                 if (event.message & resumeFlag)
5664                                 {
5665 #if TARGET_API_MAC_CARBON
5666                                         Cursor  arrow;
5667                                                 
5668                                         SetPortWindowPort( FrontWindow() );
5669                                         
5670                                         GetQDGlobalsArrow( &arrow );
5671                                         SetCursor(&arrow);
5672 #else
5673                                         SetPort(FrontWindow());
5674                                         SetCursor(&qd.arrow);
5675 #endif
5676                                 }
5677
5678                                 /* Suspend: deactivate the front window */
5679                                 else
5680                                 {
5681                                         /* Nothing */
5682                                 }
5683
5684                                 break;
5685                         }
5686
5687                         break;
5688                 }
5689
5690 #ifdef USE_SFL_CODE
5691
5692                 /* From "Steve Linberg" and "Maarten Hazewinkel" */
5693                 case kHighLevelEvent:
5694                 {
5695 #if TARGET_API_MAC_CARBON
5696                         AEProcessAppleEvent(&event);
5697 #else
5698                         /* Process apple events */
5699                         if (AEProcessAppleEvent(&event) != noErr)
5700                         {
5701                                 #ifdef JP
5702                                 plog("Apple Event Handler¤Î¥¨¥é¡¼¤Ç¤¹.");
5703                                 #else
5704                                 plog("Error in Apple Event Handler!");
5705                                 #endif
5706                         }
5707
5708                         /* Handle "quit_when_ready" */
5709                         if (quit_when_ready)
5710                         {
5711                                 /* Forget */
5712                                 quit_when_ready = FALSE;
5713
5714                                 /* Do the menu key */
5715                                 menu(MenuKey('q'));
5716
5717                                 /* Turn off the menus */
5718                                 HiliteMenu(0);
5719                         }
5720
5721                         /* Handle "open_when_ready" */
5722                         handle_open_when_ready();
5723 #endif
5724
5725                         break;
5726                 }
5727
5728 #endif
5729
5730         }
5731
5732
5733         /* Something happened */
5734         return (TRUE);
5735 }
5736
5737
5738
5739
5740 /*** Some Hooks for various routines ***/
5741
5742
5743 /*
5744  * Mega-Hack -- emergency lifeboat
5745  */
5746 static vptr lifeboat = NULL;
5747
5748
5749 /*
5750  * Hook to "release" memory
5751  */
5752 static vptr hook_rnfree(vptr v, huge size)
5753 {
5754
5755 #pragma unused (size)
5756
5757 #ifdef USE_MALLOC
5758
5759         /* Alternative method */
5760         free(v);
5761
5762 #else
5763
5764         /* Dispose */
5765         DisposePtr(v);
5766
5767 #endif
5768
5769         /* Success */
5770         return (NULL);
5771 }
5772
5773 /*
5774  * Hook to "allocate" memory
5775  */
5776 static vptr hook_ralloc(huge size)
5777 {
5778
5779 #ifdef USE_MALLOC
5780
5781         /* Make a new pointer */
5782         return (malloc(size));
5783
5784 #else
5785
5786         /* Make a new pointer */
5787         return (NewPtr(size));
5788
5789 #endif
5790
5791 }
5792
5793 /*
5794  * Hook to handle "out of memory" errors
5795  */
5796 static vptr hook_rpanic(huge size)
5797 {
5798
5799 #pragma unused (size)
5800
5801         vptr mem = NULL;
5802
5803         /* Free the lifeboat */
5804         if (lifeboat)
5805         {
5806                 /* Free the lifeboat */
5807                 DisposePtr(lifeboat);
5808
5809                 /* Forget the lifeboat */
5810                 lifeboat = NULL;
5811
5812                 /* Mega-Hack -- Warning */
5813                 #ifdef JP
5814                 mac_warning("¥á¥â¥ê¡¼¤¬Â­¤ê¤Þ¤»¤ó!\rº£¤¹¤°½ªÎ»¤·¤Æ²¼¤µ¤¤!");
5815                 #else
5816                 mac_warning("Running out of Memory!\rAbort this process now!");
5817                 #endif
5818
5819                 /* Mega-Hack -- Never leave this function */
5820                 while (TRUE) CheckEvents(TRUE);
5821         }
5822
5823         /* Mega-Hack -- Crash */
5824         return (NULL);
5825 }
5826
5827
5828 /*
5829  * Hook to tell the user something important
5830  */
5831 static void hook_plog(cptr str)
5832 {
5833         /* Warning message */
5834         mac_warning(str);
5835 }
5836
5837 /*
5838  * Hook to tell the user something, and then quit
5839  */
5840 static void hook_quit(cptr str)
5841 {
5842         /* Warning if needed */
5843         if (str) mac_warning(str);
5844
5845         /* Write a preference file */
5846         save_pref_file();
5847
5848         /* All done */
5849         ExitToShell();
5850 }
5851
5852 /*
5853  * Hook to tell the user something, and then crash
5854  */
5855 static void hook_core(cptr str)
5856 {
5857         /* XXX Use the debugger */
5858         /* DebugStr(str); */
5859
5860         /* Warning */
5861         if (str) mac_warning(str);
5862
5863         /* Warn, then save player */
5864         #ifdef JP
5865         mac_warning("Ã×̿Ū¤Ê¥¨¥é¡¼¤Ç¤¹.\r¶¯À©Åª¤Ë¥»¡¼¥Ö¤·¤Æ½ªÎ»¤·¤Þ¤¹.");
5866         #else
5867         mac_warning("Fatal error.\rI will now attempt to save and quit.");
5868         #endif
5869
5870         /* Attempt to save */
5871         #ifdef JP
5872         if (!save_player()) mac_warning("·Ù¹ð -- ¥»¡¼¥Ö¤Ë¼ºÇÔ¤·¤Þ¤·¤¿!");
5873         #else
5874         if (!save_player()) mac_warning("Warning -- save failed!");
5875         #endif
5876         
5877         /* Quit */
5878         quit(NULL);
5879 }
5880
5881
5882
5883 /*** Main program ***/
5884
5885
5886 /*
5887  * Init some stuff
5888  *
5889  * XXX XXX XXX Hack -- This function attempts to "fix" the nasty
5890  * "Macintosh Save Bug" by using "absolute" path names, since on
5891  * System 7 machines anyway, the "current working directory" often
5892  * "changes" due to background processes, invalidating any "relative"
5893  * path names.  Note that the Macintosh is limited to 255 character
5894  * path names, so be careful about deeply embedded directories...
5895  *
5896  * XXX XXX XXX Hack -- This function attempts to "fix" the nasty
5897  * "missing lib folder bug" by allowing the user to help find the
5898  * "lib" folder by hand if the "application folder" code fails...
5899  */
5900 static void init_stuff(void)
5901 {
5902         int i;
5903
5904         short vrefnum;
5905         long drefnum;
5906         long junk;
5907
5908         SFTypeList types;
5909         SFReply reply;
5910
5911         Rect r;
5912         Point topleft;
5913
5914         char path[1024];
5915
5916         BitMap screen;
5917         Rect screenRect;
5918
5919 #if TARGET_API_MAC_CARBON
5920         OSErr err = noErr;
5921         NavDialogOptions dialogOptions;
5922         FSSpec theFolderSpec;
5923         NavReplyRecord theReply;
5924 #endif
5925         /* Fake rectangle */
5926         r.left = 0;
5927         r.top = 0;
5928         r.right = 344;
5929         r.bottom = 188;
5930
5931         /* Center it */
5932 #if TARGET_API_MAC_CARBON
5933         screenRect = GetQDGlobalsScreenBits(&screen)->bounds;
5934 #else
5935         screenRect = qd.screenBits.bounds;
5936 #endif
5937         center_rect(&r, &screenRect);
5938
5939         /* Extract corner */
5940         topleft.v = r.top;
5941         topleft.h = r.left;
5942
5943
5944         /* Default to the "lib" folder with the application */
5945         refnum_to_name(path, app_dir, app_vol, (char*)("\plib:"));
5946
5947
5948         /* Check until done */
5949         while (1)
5950         {
5951                 /* Prepare the paths */
5952                 init_file_paths(path);
5953
5954                 /* Build the filename */
5955 #ifdef JP
5956                 path_build(path, sizeof(path), ANGBAND_DIR_FILE, "news_j.txt");
5957 #else
5958                 path_build(path, sizeof(path), ANGBAND_DIR_FILE, "news.txt");
5959 #endif
5960
5961                 /* Attempt to open and close that file */
5962                 if (0 == fd_close(fd_open(path, O_RDONLY))) break;
5963
5964                 /* Warning */
5965 #ifdef JP
5966                 plog_fmt("'%s' ¥Õ¥¡¥¤¥ë¤ò¥ª¡¼¥×¥ó½ÐÍè¤Þ¤»¤ó.", path);
5967 #else
5968                 plog_fmt("Unable to open the '%s' file.", path);
5969 #endif
5970
5971                 /* Warning */
5972 #ifdef JP
5973                 plog("Hengband¤Î'lib'¥Õ¥©¥ë¥À¤¬Â¸ºß¤·¤Ê¤¤¤«Àµ¤·¤¯Ìµ¤¤²ÄǽÀ­¤¬¤¢¤ê¤Þ¤¹.");
5974 #else
5975                 plog("The Angband 'lib' folder is probably missing or misplaced.");
5976 #endif
5977
5978                 /* Warning */
5979 #ifdef JP
5980                 plog("Please 'open' any file in any sub-folder of the 'lib' folder.");
5981 #else
5982                 plog("Please 'open' any file in any sub-folder of the 'lib' folder.");
5983 #endif
5984                 
5985 #if TARGET_API_MAC_CARBON
5986                 /* Ask the user to choose the lib folder */
5987                 err = NavGetDefaultDialogOptions(&dialogOptions);
5988
5989                 /* Paranoia */
5990                 if (err != noErr) quit(NULL);
5991
5992                 /* Set default location option */
5993                 dialogOptions.dialogOptionFlags |= kNavSelectDefaultLocation;
5994
5995                 /* Clear preview option */
5996                 dialogOptions.dialogOptionFlags &= ~(kNavAllowPreviews);
5997
5998                 /* Forbit selection of multiple files */
5999                 dialogOptions.dialogOptionFlags &= ~(kNavAllowMultipleFiles);
6000
6001                 /* Display location */
6002                 dialogOptions.location = topleft;
6003
6004                 /* Load the message for the missing folder from the resource fork */
6005                 GetIndString(dialogOptions.message, 128, 1);
6006
6007                 /* Wait for the user to choose a folder */
6008                 err = NavChooseFolder(
6009                         nil,
6010                         &theReply,
6011                         &dialogOptions,
6012                         nil,
6013                         nil,
6014                         nil);
6015
6016                 /* Assume the player doesn't want to go on */
6017                 if ((err != noErr) || !theReply.validRecord) quit(NULL);
6018
6019                 /* Retrieve FSSpec from the reply */
6020                 {
6021                         AEKeyword theKeyword;
6022                         DescType actualType;
6023                         Size actualSize;
6024
6025                         /* Get a pointer to selected folder */
6026                         err = AEGetNthPtr(
6027                                 &(theReply.selection),
6028                                 1,
6029                                 typeFSS,
6030                                 &theKeyword,
6031                                 &actualType,
6032                                 &theFolderSpec,
6033                                 sizeof(FSSpec),
6034                                 &actualSize);
6035
6036                         /* Paranoia */
6037                         if (err != noErr) quit(NULL);
6038                 }
6039
6040                 /* Free navitagor reply */
6041                 err = NavDisposeReply(&theReply);
6042
6043                 /* Paranoia */
6044                 if (err != noErr) quit(NULL);
6045
6046                 /* Extract textual file name for given file */
6047                 refnum_to_name(
6048                         path,
6049                         theFolderSpec.parID,
6050                         theFolderSpec.vRefNum,
6051                         (char *)theFolderSpec.name);
6052 #else
6053                 /* Allow "text" files */
6054                 types[0] = 'TEXT';
6055
6056                 /* Allow "save" files */
6057                 types[1] = 'SAVE';
6058
6059                 /* Allow "data" files */
6060                 types[2] = 'DATA';
6061
6062                 /* Get any file */
6063                 SFGetFile(topleft, "\p", NULL, 3, types, NULL, &reply);
6064
6065                 /* Allow cancel */
6066                 if (!reply.good) quit(NULL);
6067
6068                 /* Extract textual file name for given file */
6069                 GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
6070                 refnum_to_name(path, drefnum, vrefnum, (char*)reply.fName);
6071 #endif
6072
6073                 /* Hack -- Remove the "filename" */
6074                 i = strlen(path) - 1;
6075                 while ((i > 0) && (path[i] != ':')) i--;
6076                 if (path[i] == ':') path[i+1] = '\0';
6077
6078                 /* Hack -- allow "lib" folders */
6079                 if (suffix(path, "lib:")) continue;
6080
6081                 /* Hack -- Remove the "sub-folder" */
6082                 i = i - 1;
6083                 while ((i > 1) && (path[i] != ':')) i--;
6084                 if (path[i] == ':') path[i+1] = '\0';
6085         }
6086 }
6087
6088
6089 /*
6090  * Macintosh Main loop
6091  */
6092 void main(void)
6093 {
6094         EventRecord tempEvent;
6095         int numberOfMasters = 10;
6096
6097 #if !TARGET_API_MAC_CARBON
6098         /* Increase stack space by 64K */
6099         SetApplLimit(GetApplLimit() - 131072L);//65536L);
6100
6101         /* Stretch out the heap to full size */
6102         MaxApplZone();
6103 #endif
6104
6105         /* Get more Masters */
6106         while (numberOfMasters--) MoreMasters();
6107
6108 #if !TARGET_API_MAC_CARBON
6109         /* Set up the Macintosh */
6110         InitGraf(&qd.thePort);
6111         InitFonts();
6112         InitWindows();
6113         InitMenus();
6114         /* TEInit(); */
6115         InitDialogs(NULL);
6116 #endif
6117         InitCursor();
6118
6119 #ifdef JP
6120         KeyScript(smRoman);
6121 #endif
6122
6123         /* Flush events */
6124         FlushEvents(everyEvent, 0);
6125
6126         /* Flush events some more (?) */
6127         (void)EventAvail(everyEvent, &tempEvent);
6128         (void)EventAvail(everyEvent, &tempEvent);
6129         (void)EventAvail(everyEvent, &tempEvent);
6130
6131
6132 #ifdef ANGBAND_LITE_MAC
6133
6134         /* Nothing */
6135
6136 #else /* ANGBAND_LITE_MAC */
6137
6138 # if defined(powerc) || defined(__powerc)
6139
6140         /* Assume System 7 */
6141         
6142         /* Assume Color Quickdraw */
6143
6144 # else
6145
6146         /* Block */
6147         if (TRUE)
6148         {
6149                 OSErr err;
6150                 long versionNumber;
6151
6152                 /* Check the Gestalt */
6153                 err = Gestalt(gestaltSystemVersion, &versionNumber);
6154
6155                 /* Check the version */
6156                 if ((err != noErr) || (versionNumber < 0x0700))
6157                 {
6158                         #ifdef JP
6159                         quit("¤³¤Î¥×¥í¥°¥é¥à¤Ï´Á»úTalk7.x.x°Ê¹ß¤ÇÆ°ºî¤·¤Þ¤¹.");
6160                         #else
6161                         quit("You must have System 7 to use this program.");
6162                         #endif
6163                 }
6164         }
6165
6166         /* Block */
6167         if (TRUE)
6168         {
6169                 SysEnvRec env;
6170
6171                 /* Check the environs */
6172                 if (SysEnvirons(1, &env) != noErr)
6173                 {
6174                         #ifdef JP
6175                         quit("SysEnvirons ¥³¡¼¥ë¤Ï¼ºÇÔ¤·¤Þ¤·¤¿¡ª");
6176                         #else
6177                         quit("The SysEnvirons call failed!");
6178                         #endif
6179                 }
6180
6181                 /* Check for System Seven Stuff */
6182                 if (env.systemVersion < 0x0700)
6183                 {
6184                         #ifdef JP
6185                         quit("¤³¤Î¥×¥í¥°¥é¥à¤Ï´Á»úTalk7.x.x°Ê¹ß¤ÇÆ°ºî¤·¤Þ¤¹.");
6186                         #else
6187                         quit("You must have System 7 to use this program.");
6188                         #endif
6189                 }
6190
6191                 /* Check for Color Quickdraw */
6192                 if (!env.hasColorQD)
6193                 {
6194                         #ifdef JP
6195                         quit("¤³¤Î¥×¥í¥°¥é¥à¤ÏColor Quickdraw¤¬Ìµ¤¤¤ÈÆ°ºî¤·¤Þ¤»¤ó.");
6196                         #else
6197                         quit("You must have Color Quickdraw to use this program.");
6198                         #endif
6199                 }
6200         }
6201
6202 # endif
6203
6204 #endif /* ANGBAND_LITE_MAC */
6205
6206         /* 
6207          * Remember Mac OS version, in case we have to cope with version-specific
6208          * problems
6209          */
6210         (void)Gestalt(gestaltSystemVersion, &mac_os_version);
6211
6212 #ifdef USE_SFL_CODE
6213         /* Obtain a "Universal Procedure Pointer" */
6214         AEH_Start_UPP = NewAEEventHandlerUPP(AEH_Start);
6215         /* Install the hook (ignore error codes) */
6216         AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, AEH_Start_UPP,
6217                               0L, FALSE);
6218
6219         /* Obtain a "Universal Procedure Pointer" */
6220         AEH_Quit_UPP = NewAEEventHandlerUPP(AEH_Quit);
6221         /* Install the hook (ignore error codes) */
6222         AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, AEH_Quit_UPP,
6223                               0L, FALSE);
6224
6225         /* Obtain a "Universal Procedure Pointer" */
6226         AEH_Print_UPP = NewAEEventHandlerUPP(AEH_Print);
6227         /* Install the hook (ignore error codes) */
6228         AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, AEH_Print_UPP,
6229                               0L, FALSE);
6230
6231         /* Obtain a "Universal Procedure Pointer" */
6232         AEH_Open_UPP = NewAEEventHandlerUPP(AEH_Open);
6233         /* Install the hook (ignore error codes) */
6234         AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, AEH_Open_UPP,
6235                               0L, FALSE);
6236 #endif
6237
6238         /* Find the current application */
6239         SetupAppDir();
6240
6241
6242         /* Mark ourself as the file creator */
6243         _fcreator = 'Heng';
6244
6245         /* Default to saving a "text" file */
6246         _ftype = 'TEXT';
6247
6248
6249 #if defined(__MWERKS__)
6250
6251         /* Obtian a "Universal Procedure Pointer" */
6252 #if TARGET_API_MAC_CARBON
6253         ynfilterUPP = NewModalFilterUPP(ynfilter);
6254 #else
6255         ynfilterUPP = NewModalFilterProc(ynfilter);
6256 #endif
6257
6258 #endif
6259
6260
6261         /* Hook in some "z-virt.c" hooks */
6262         rnfree_aux = hook_rnfree;
6263         ralloc_aux = hook_ralloc;
6264         rpanic_aux = hook_rpanic;
6265
6266         /* Hooks in some "z-util.c" hooks */
6267         plog_aux = hook_plog;
6268         quit_aux = hook_quit;
6269         core_aux = hook_core;
6270
6271         BackColor(blackColor);
6272         ForeColor(whiteColor);
6273
6274         /* Show the "watch" cursor */
6275         SetCursor(*(GetCursor(watchCursor)));
6276
6277         /* Prepare the menubar */
6278         init_menubar();
6279
6280         /* Prepare the windows */
6281         init_windows();
6282
6283         init_sound();
6284
6285         init_graf();
6286         
6287         /* Hack -- process all events */
6288         while (CheckEvents(TRUE)) /* loop */;
6289
6290         /* Reset the cursor */
6291 #if TARGET_API_MAC_CARBON
6292         {
6293                 Cursor  arrow;
6294                 GetQDGlobalsArrow( &arrow );
6295                 SetCursor(&arrow);
6296         }
6297 #else
6298         SetCursor( &qd.arrow );
6299 #endif
6300
6301
6302         /* Mega-Hack -- Allocate a "lifeboat" */
6303         lifeboat = NewPtr(16384);
6304
6305         /* Note the "system" */
6306         ANGBAND_SYS = "mac";
6307
6308         /* Initialize */
6309         init_stuff();
6310
6311         /* Catch nasty signals */
6312         signals_init();
6313
6314         /* Initialize */
6315         init_angband();
6316
6317
6318         /* Hack -- process all events */
6319         while (CheckEvents(TRUE)) /* loop */;
6320
6321
6322         /* We are now initialized */
6323         initialized = TRUE;
6324
6325
6326         /* Handle "open_when_ready" */
6327         handle_open_when_ready();
6328
6329 #ifdef CHUUKEI
6330         init_chuukei();
6331 #endif
6332
6333         /* Prompt the user */
6334 #ifdef JP
6335         prt("'¥Õ¥¡¥¤¥ë'¥á¥Ë¥å¡¼¤è¤ê'¿·µ¬'¤Þ¤¿¤Ï'³«¤¯...'¤òÁªÂò¤·¤Æ¤¯¤À¤µ¤¤¡£", 23, 10);
6336 #else
6337         prt("[Choose 'New' or 'Open' from the 'File' menu]", 23, 15);
6338 #endif
6339
6340         /* Flush the prompt */
6341         Term_fresh();
6342
6343
6344         /* Hack -- Process Events Forever */
6345         while (TRUE) CheckEvents(TRUE);
6346 }
6347