OSDN Git Service

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