1 /* File: main-mac.c */
3 /* Purpose: Simple support for MACINTOSH Angband */
6 * This file should only be compiled with the "Macintosh" version
8 * This file written by "Ben Harrison (benh@phial.com)".
10 * Some code adapted from "MacAngband 2.6.1" by Keith Randall
12 * Maarten Hazewinkel (mmhazewi@cs.ruu.nl) provided some initial
13 * suggestions for the PowerMac port.
15 * Steve Linberg (slinberg@crocker.com) provided the code surrounded
18 * The graphics code is adapted from an extremely minimal subset of
19 * the code from "Sprite World II", an amazing animation package.
21 * See "z-term.c" for info on the concept of the "generic terminal"
23 * The preference file is now a text file named "Angband preferences".
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).
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.
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".
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.
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.
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.
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.
59 * Important Resources in the resource file:
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)
66 * DLOG 128 = "About Angband..."
68 * ALRT 128 = unused (?)
69 * ALRT 129 = "Warning..."
70 * ALRT 130 = "Are you sure you want to quit without saving?"
72 * DITL 128 = body for DLOG 128
73 * DITL 129 = body for ALRT 129
74 * DITL 130 = body for ALRT 130
76 * ICON 128 = "warning" icon
78 * MENU 128 = apple (about, -, ...)
79 * MENU 129 = File (new, open, close, save, -, exit, quit)
80 * MENU 130 = Edit (undo, -, cut, copy, paste, clear)
82 * PICT 1001 = Graphics tile set
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:*" (?)
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
102 * Reasons for each header file:
104 * angband.h = Angband header file
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
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
139 #include <Carbon/Carbon.h>
140 #include <QuickTime/QuickTime.h>
141 #include <CoreServices/CoreServices.h>
142 #include <CoreFoundation/CoreFoundation.h>
144 #define TARGET_API_MAC_CARBON 1
146 #else /* MACH_O_CARBON */
150 #include <QuickDraw.h>
156 #include <Palettes.h>
157 #include <StandardFile.h>
158 #include <DiskInit.h>
159 #include <ToolUtils.h>
162 #include <Resources.h>
163 #include <Controls.h>
166 #include <QDOffscreen.h>
168 #if TARGET_API_MAC_CARBON
169 #include <Navigation.h>
170 #include <CFPreferences.h>
171 #include <CFNumber.h>
173 # include <CarbonStdCLib.h>
183 #endif /* MACH_O_CARBON */
186 * Cleaning up a couple of things to make these easier to change --AR
188 #define PREF_FILE_NAME _("Hengband Preferences", "Hengband-E Preferences")
191 * Use "malloc()" instead of "NewPtr()"
193 /* #define USE_MALLOC */
196 /* Default creator signature */
197 #ifndef ANGBAND_CREATOR
198 # define ANGBAND_CREATOR 'Heng'
202 #if defined(powerc) || defined(__powerc)
205 * Disable "LITE" version
207 # undef ANGBAND_LITE_MAC
212 #ifdef ANGBAND_LITE_MAC
215 * Maximum number of windows
217 # define MAX_TERM_DATA 1
219 #else /* ANGBAND_LITE_MAC */
222 * Maximum number of windows
224 # define MAX_TERM_DATA 8
227 * Activate some special code
229 # define USE_SFL_CODE
232 * Use rewritten asynchronous sound player
234 #define USE_ASYNC_SOUND
241 #endif /* MACH_O_CARBON */
242 #endif /* ANGBAND_LITE_MAC */
246 #ifndef MACH_O_CARBON
250 * Include the necessary header files
252 #include <AppleEvents.h>
257 #endif /* !MACH_O_CARBON */
260 * Globals for MPW compilation
262 #if defined(MACH_O_CARBON) || defined(MAC_MPW)
264 #if !TARGET_API_MAC_CARBON
276 * The Angband Color Set (0 to 15):
277 * Black, White, Slate, Orange, Red, Blue, Green, Umber
278 * D-Gray, L-Gray, Violet, Yellow, L-Red, L-Blue, L-Green, L-Umber
280 * Colors 8 to 15 are basically "enhanced" versions of Colors 0 to 7.
282 * On the Macintosh, we use color quickdraw, and we use actual "RGB"
283 * values below to choose the 16 colors.
285 * If we are compiled for ancient machines, we bypass color and simply
286 * draw everything in white (letting "z-term.c" automatically convert
287 * "black" into "wipe" calls).
289 static RGBColor foo[16] =
291 {0x0000, 0x0000, 0x0000}, /* TERM_DARK */
292 {0xFFFF, 0xFFFF, 0xFFFF}, /* TERM_WHITE */
293 {0x8080, 0x8080, 0x8080}, /* TERM_SLATE */
294 {0xFFFF, 0x8080, 0x0000}, /* TERM_ORANGE */
295 {0xC0C0, 0x0000, 0x0000}, /* TERM_RED */
296 {0x0000, 0x8080, 0x4040}, /* TERM_GREEN */
297 {0x0000, 0x0000, 0xFFFF}, /* TERM_BLUE */
298 {0x8080, 0x4040, 0x0000}, /* TERM_UMBER */
299 {0x4040, 0x4040, 0x4040}, /* TERM_L_DARK */
300 {0xC0C0, 0xC0C0, 0xC0C0}, /* TERM_L_WHITE */
301 {0xFFFF, 0x0000, 0xFFFF}, /* TERM_VIOLET */
302 {0xFFFF, 0xFFFF, 0x0000}, /* TERM_YELLOW */
303 {0xFFFF, 0x0000, 0x0000}, /* TERM_L_RED */
304 {0x0000, 0xFFFF, 0x0000}, /* TERM_L_GREEN */
305 {0x0000, 0xFFFF, 0xFFFF}, /* TERM_L_BLUE */
306 {0xC0C0, 0x8080, 0x4040} /* TERM_L_UMBER */
315 typedef struct term_data term_data;
328 #ifdef ANGBAND_LITE_MAC
332 #else /* ANGBAND_LITE_MAC */
344 #endif /* ANGBAND_LITE_MAC */
387 * Forward declare -- see below
389 static bool CheckEvents(bool wait);
391 #ifndef MACH_O_CARBON
394 * Hack -- location of the main directory
396 static short app_vol;
399 #endif /* !MACH_O_CARBON */
402 * Delay handling of double-clicked savefiles
404 Boolean open_when_ready = FALSE;
407 * Delay handling of pre-emptive "quit" event
409 Boolean quit_when_ready = FALSE;
413 * Hack -- game in progress
415 static int game_in_progress = 0;
419 * Only do "SetPort()" when needed
421 static WindowPtr active = NULL;
426 * An array of term_data's
428 static term_data data[MAX_TERM_DATA];
433 * Note when "open"/"new" become valid
435 static bool initialized = FALSE;
438 * Version of Mac OS - for version specific bug workarounds (; ;)
440 static long mac_os_version;
443 #if defined(__MWERKS__)
445 * CodeWarrior uses Universal Procedure Pointers
447 static ModalFilterUPP ynfilterUPP;
449 #endif /* __MWERKS__ */
456 AEEventHandlerUPP AEH_Start_UPP;
457 AEEventHandlerUPP AEH_Quit_UPP;
458 AEEventHandlerUPP AEH_Print_UPP;
459 AEEventHandlerUPP AEH_Open_UPP;
464 * Convert refnum+vrefnum+fname into a full file name
465 * Store this filename in 'buf' (make sure it is long enough)
466 * Note that 'fname' looks to be a "pascal" string
468 #if TARGET_API_MAC_CARBON
469 static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname)
484 for (j=1; j<=fname[0]; j++)
486 res[i-fname[0]+j] = fname[j];
495 pb.dirInfo.ioDrDirID=pb.dirInfo.ioDrParID;
496 err = FSMakeFSSpec( vref, dirID, "\p", &spec );
502 for (j=1; j<=spec.name[0]; j++)
504 res[i-spec.name[0]+j] = spec.name[j];
511 /* Extract the result */
512 for (j = 0, i++; res[i]; j++, i++) buf[j] = res[i];
516 static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname)
528 for (j=1; j<=fname[0]; j++)
530 res[i-fname[0]+j] = fname[j];
534 pb.ioCompletion=NULL;
536 pb.ioVRefNum=vrefnum;
542 pb.ioDrDirID=pb.ioDrParID;
543 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
545 for (j=1; j<=name[0]; j++)
547 res[i-name[0]+j] = name[j];
551 if (pb.ioDrDirID == fsRtDirID) break;
554 /* Extract the result */
555 for (j = 0, i++; res[i]; j++, i++) buf[j] = res[i];
560 #if TARGET_API_MAC_CARBON
561 pascal OSErr FSpLocationFromFullPath(short fullPathLength,
562 const void *fullPath,
570 /* Create a minimal alias from the full pathname */
571 nullString[0] = 0; /* null string to indicate no zone or server name */
572 result = NewAliasMinimalFromFullPath(fullPathLength, fullPath, nullString, nullString, &alias);
573 if ( result == noErr )
575 /* Let the Alias Manager resolve the alias. */
576 result = ResolveAlias(NULL, alias, spec, &wasChanged);
578 /* work around Alias Mgr sloppy volume matching bug */
579 if ( spec->vRefNum == 0 )
581 /* invalidate wrong FSSpec */
586 DisposeHandle((Handle)alias); /* Free up memory used */
595 * XXX XXX XXX Allow the system to ask us for a filename
597 static bool askfor_file(char *buf, int len)
605 /* Default file name */
606 sprintf((char*)dflt + 1, "%s's description", buf);
607 dflt[0] = strlen((char*)dflt + 1);
609 /* Ask for a file name */
610 topleft.h=(qd.screenBits.bounds.left+qd.screenBits.bounds.right)/2-344/2;
611 topleft.v=(2*qd.screenBits.bounds.top+qd.screenBits.bounds.bottom)/3-188/2;
612 SFPutFile(topleft, "\pSelect a filename:", dflt, NULL, &reply);
613 /* StandardPutFile("\pSelect a filename:", dflt, &reply); */
621 GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
623 /* Extract the name */
624 refnum_to_name(buf, drefnum, vrefnum, (char*)reply.fName);
636 #if !TARGET_API_MAC_CARBON
637 static void local_to_global( Rect *r )
644 LocalToGlobal( &temp );
652 LocalToGlobal( &temp );
657 #endif /* !TARGET_API_MAC_CARBON */
659 static void global_to_local( Rect *r )
666 GlobalToLocal( &temp );
674 GlobalToLocal( &temp );
684 * Convert pathname to an appropriate format, because MPW's
685 * CarbonStdCLib chose to use system's native path format,
686 * making our lives harder to create binaries that run on
687 * OS 8/9 and OS X :( -- pelpel
689 void convert_pathname(char* path)
693 /* Nothing has to be done for CarbonLib on Classic */
694 if (mac_os_version >= 0x1000)
696 /* Convert to POSIX style */
697 ConvertHFSPathToUnixPath(path, buf);
699 /* Copy the result back */
707 # ifdef CHECK_MODIFICATION_TIME
710 * Although there is no easy way to emulate fstat in the old interface,
711 * we still can do stat-like things, because Mac OS is an OS.
713 static int get_modification_time(cptr path, u32b *mod_time)
719 /* Paranoia - make sure the pathname fits in Str255 */
721 if (i > 255) return (-1);
723 /* Convert pathname to a Pascal string */
724 strncpy((char *)pathname + 1, path, 255);
727 /* Set up parameter block */
728 pb.hFileInfo.ioNamePtr = pathname;
729 pb.hFileInfo.ioFDirIndex = 0;
730 pb.hFileInfo.ioVRefNum = app_vol;
731 pb.hFileInfo.ioDirID = 0;
733 /* Get catalog information of the file */
734 if (PBGetCatInfoSync(&pb) != noErr) return (-1);
736 /* Set modification date and time */
737 *mod_time = pb.hFileInfo.ioFlMdDat;
745 * A (non-Mach-O) Mac OS version of check_modification_time, for those
746 * compilers without good enough POSIX-compatibility libraries XXX XXX
748 errr check_modification_date(int fd, cptr template_file)
751 u32b txt_stat, raw_stat;
756 /* Build the file name */
757 path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, template_file);
760 convert_pathname(buf);
762 /* Obtain modification time */
763 if (get_modification_time(buf, &txt_stat)) return (-1);
765 /* XXX Build filename of the corresponding *.raw file */
766 strnfmt(fname, sizeof(fname), "%s", template_file);
769 p = strrchr(fname, '.');
772 if (p == NULL) return (-1);
774 /* Substitute ".raw" for ".txt" */
777 /* Build the file name of the raw file */
778 path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, fname);
781 convert_pathname(buf);
783 /* Obtain modification time */
784 if (get_modification_time(buf, &raw_stat)) return (-1);
786 /* Ensure the text file is not newer than the raw file */
787 if (txt_stat > raw_stat) return (-1);
789 /* Keep using the current .raw file */
793 # endif /* CHECK_MODIFICATION_TIME */
798 * Center a rectangle inside another rectangle
800 static void center_rect(Rect *r, Rect *s)
802 int centerx = (s->left + s->right)/2;
803 int centery = (2*s->top + s->bottom)/3;
804 int dx = centerx - (r->right - r->left)/2 - r->left;
805 int dy = centery - (r->bottom - r->top)/2 - r->top;
815 /* Carbon File Manager utilities by pelpel */
819 * Convert a pathname to a corresponding FSSpec.
820 * Returns noErr on success.
822 static OSErr path_to_spec(const char *path, FSSpec *spec)
827 /* Convert pathname to FSRef ... */
828 err = FSPathMakeRef(path, &ref, NULL);
829 if (err != noErr) return (err);
831 /* ... then FSRef to FSSpec */
832 err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
834 /* Inform caller of success or failure */
841 * Convert a FSSpec to a corresponding pathname.
842 * Returns noErr on success.
844 static OSErr spec_to_path(const FSSpec *spec, char *buf, size_t size)
849 /* Convert FSSpec to FSRef ... */
850 err = FSpMakeFSRef(spec, &ref);
851 if (err != noErr) return (err);
853 /* ... then FSRef to pathname */
854 err = FSRefMakePath(&ref, buf, size);
856 /* Inform caller of success or failure */
862 * (Carbon) [via path_to_spec]
863 * Set creator and filetype of a file specified by POSIX-style pathname.
864 * Returns 0 on success, -1 in case of errors.
866 void fsetfileinfo(cptr pathname, OSType fcreator, OSType ftype)
872 /* Convert pathname to FSSpec */
873 if (path_to_spec(pathname, &spec) != noErr) return;
875 /* Obtain current finder info of the file */
876 if (FSpGetFInfo(&spec, &info) != noErr) return;
878 /* Overwrite creator and type */
879 info.fdCreator = fcreator;
881 err = FSpSetFInfo(&spec, &info);
888 #else /* MACH_O_CARBON */
892 * Convert a pascal string in place
894 * This function may be defined elsewhere, but since it is so
895 * small, it is not worth finding the proper function name for
896 * all the different platforms.
898 static void ptocstr(StringPtr src)
902 /* Hack -- pointer */
903 char *s = (char*)(src);
905 /* Hack -- convert the string */
906 for (i = s[0]; i; i--, s++) s[0] = s[1];
908 /* Hack -- terminate the string */
913 #if defined(USE_SFL_CODE)
917 * The following three routines (pstrcat, pstrinsert, and PathNameFromDirID)
918 * were taken from the Think Reference section called "Getting a Full Pathname"
919 * (under the File Manager section). We need PathNameFromDirID to get the
920 * full pathname of the opened savefile, making no assumptions about where it
923 * I had to hack PathNameFromDirID a little for MetroWerks, but it's awfully
926 static void pstrcat(StringPtr dst, StringPtr src)
929 BlockMove(src + 1, dst + *dst + 1, *src);
931 /* adjust length byte */
936 * pstrinsert - insert string 'src' at beginning of string 'dst'
938 static void pstrinsert(StringPtr dst, StringPtr src)
940 /* make room for new string */
941 BlockMove(dst + 1, dst + *src + 1, *dst);
943 /* copy new string in */
944 BlockMove(src + 1, dst + 1, *src);
946 /* adjust length byte */
950 static void PathNameFromDirID(long dirID, short vRefNum, StringPtr fullPathName)
953 Str255 directoryName;
956 fullPathName[0] = '\0';
958 block.dirInfo.ioDrParID = dirID;
959 block.dirInfo.ioNamePtr = directoryName;
963 block.dirInfo.ioVRefNum = vRefNum;
964 block.dirInfo.ioFDirIndex = -1;
965 block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID;
966 err = PBGetCatInfo(&block, FALSE);
967 pstrcat(directoryName, (StringPtr)"\p:");
968 pstrinsert(fullPathName, directoryName);
969 if (block.dirInfo.ioDrDirID == 2) break;
974 #endif /* MACH_O_CARBON */
977 * Activate a given window, if necessary
979 static void activate(WindowPtr w)
985 #if TARGET_API_MAC_CARBON
986 if (w) SetPortWindowPort(w);
998 * Display a warning message
1000 static void mac_warning(cptr warning)
1005 /* Limit of 250 chars */
1006 len = strlen(warning);
1007 if (len > 250) len = 250;
1009 /* Make a "Pascal" string */
1011 for (i=0; i<len; i++) text[i+1] = warning[i];
1013 /* Prepare the dialog box values */
1014 ParamText(text, "\p", "\p", "\p");
1016 /* Display the Alert, wait for Okay */
1022 /*** Some generic functions ***/
1025 #ifdef ANGBAND_LITE_MAC
1028 * Hack -- activate a color (0 to 255)
1030 #define term_data_color(TD,A) /* Nothing */
1032 #else /* ANGBAND_LITE_MAC */
1035 * Hack -- activate a color (0 to 255)
1037 static void term_data_color(term_data *td, int a)
1043 /* Extract the R,G,B data */
1044 rv = angband_color_table[a][1];
1045 gv = angband_color_table[a][2];
1046 bv = angband_color_table[a][3];
1049 color.red = (rv | (rv << 8));
1050 color.green = (gv | (gv << 8));
1051 color.blue = (bv | (bv << 8));
1053 /* Activate the color */
1054 RGBForeColor(&color);
1056 /* Memorize color */
1060 #endif /* ANGBAND_LITE_MAC */
1064 * Hack -- Apply and Verify the "font" info
1066 * This should usually be followed by "term_data_check_size()"
1068 static void term_data_check_font(term_data *td)
1074 WindowPtr old = active;
1080 /* Instantiate font */
1081 TextFont(td->font_id);
1082 TextSize(td->font_size);
1083 TextFace(td->font_face);
1085 /* Extract the font info */
1088 /* Assume monospaced */
1089 td->font_mono = TRUE;
1091 /* Extract the font sizing values XXX XXX XXX */
1092 td->font_wid = CharWidth('@'); /* info.widMax; */
1093 td->font_hgt = info.ascent + info.descent;
1095 td->font_o_y = info.ascent;
1097 /* Check important characters */
1098 for (i = 33; i < 127; i++)
1100 /* Hack -- notice non-mono-space */
1101 if (td->font_wid != CharWidth(i)) td->font_mono = FALSE;
1103 /* Hack -- collect largest width */
1104 if (td->font_wid < CharWidth(i)) td->font_wid = CharWidth(i);
1107 /* Set default offsets */
1108 td->tile_o_x = td->font_o_x;
1109 td->tile_o_y = td->font_o_y;
1111 /* Set default tile size */
1112 if( td->tile_wid == 0 && td->tile_hgt == 0 ){
1113 td->tile_wid = td->font_wid;
1114 td->tile_hgt = td->font_hgt;
1117 /* Re-activate the old window */
1123 * Hack -- Apply and Verify the "size" info
1125 static void term_data_check_size(term_data *td)
1129 #if TARGET_API_MAC_CARBON
1130 GetQDGlobalsScreenBits( &screen );
1132 screen = qd.screenBits;
1134 /* Minimal window size */
1137 /* Enforce minimal size */
1138 if (td->cols < 80) td->cols = 80;
1139 if (td->rows < 24) td->rows = 24;
1142 /* Allow small windows for the rest */
1145 if (td->cols < 1) td->cols = 1;
1146 if (td->rows < 1) td->rows = 1;
1149 /* Minimal tile size */
1150 if (td->tile_wid < 4) td->tile_wid = 4;
1151 if (td->tile_hgt < 4) td->tile_hgt = 4;
1153 /* Default tile offsets */
1154 td->tile_o_x = (td->tile_wid - td->font_wid) / 2;
1155 td->tile_o_y = (td->tile_hgt - td->font_hgt) / 2;
1157 /* Minimal tile offsets */
1158 if (td->tile_o_x < 0) td->tile_o_x = 0;
1159 if (td->tile_o_y < 0) td->tile_o_y = 0;
1161 /* Apply font offsets */
1162 td->tile_o_x += td->font_o_x;
1163 td->tile_o_y += td->font_o_y;
1165 /* Calculate full window size */
1166 td->size_wid = td->cols * td->tile_wid + td->size_ow1 + td->size_ow2;
1167 td->size_hgt = td->rows * td->tile_hgt + td->size_oh1 + td->size_oh2;
1169 /* Verify the top */
1170 if (td->r.top > screen.bounds.bottom - td->size_hgt)
1172 td->r.top = screen.bounds.bottom - td->size_hgt;
1175 /* Verify the top */
1176 if (td->r.top < screen.bounds.top + 30)
1178 td->r.top = screen.bounds.top + 30;
1181 /* Verify the left */
1182 if (td->r.left > screen.bounds.right - td->size_wid)
1184 td->r.left = screen.bounds.right - td->size_wid;
1187 /* Verify the left */
1188 if (td->r.left < screen.bounds.left)
1190 td->r.left = screen.bounds.left;
1193 /* Calculate bottom right corner */
1194 td->r.right = td->r.left + td->size_wid;
1195 td->r.bottom = td->r.top + td->size_hgt;
1197 /* Assume no graphics */
1198 td->t->higher_pict = FALSE;
1199 td->t->always_pict = FALSE;
1201 #ifdef ANGBAND_LITE_MAC
1205 #else /* ANGBAND_LITE_MAC */
1207 /* Handle graphics */
1210 /* Use higher_pict whenever possible */
1211 if (td->font_mono) td->t->higher_pict = TRUE;
1213 /* Use always_pict only when necessary */
1214 else td->t->always_pict = TRUE;
1217 #endif /* ANGBAND_LITE_MAC */
1219 /* Fake mono-space */
1220 if (!td->font_mono ||
1221 (td->font_wid != td->tile_wid) ||
1222 (td->font_hgt != td->tile_hgt))
1224 /* Handle fake monospace -- this is SLOW */
1225 if (td->t->higher_pict) td->t->higher_pict = FALSE;
1226 td->t->always_pict = TRUE;
1231 * Hack -- resize a term_data
1233 * This should normally be followed by "term_data_resize()"
1235 static void term_data_resize(term_data *td)
1237 /* Actually resize the window */
1238 SizeWindow(td->w, td->size_wid, td->size_hgt, 0);
1244 * Hack -- redraw a term_data
1246 * Note that "Term_redraw()" calls "TERM_XTRA_CLEAR"
1248 static void term_data_redraw(term_data *td)
1252 /* Activate the term */
1253 Term_activate(td->t);
1255 /* Redraw the contents */
1258 /* Flush the output */
1261 /* Restore the old term */
1264 /* No need to redraw */
1265 #if TARGET_API_MAC_CARBON
1267 RgnHandle theRgn = NewRgn();
1268 GetWindowRegion( td->w, kWindowContentRgn, theRgn );
1269 ValidWindowRgn( (WindowRef)(td->w), theRgn );
1270 DisposeRgn( theRgn );
1273 ValidRect(&td->w->portRect);
1281 #ifdef ANGBAND_LITE_MAC
1285 #else /* ANGBAND_LITE_MAC */
1293 * PICT id of image tiles, set by Term_xtra_mac_react
1295 #ifdef MACH_O_CARBON
1296 static CFStringRef pictID = NULL;
1298 static int pictID = 0;
1299 #endif /* MACH_O_CARBON */
1302 * Width and height of a tile in pixels
1304 static int grafWidth = 0;
1305 static int grafHeight = 0;
1308 * Numbers of rows and columns in tiles, calculated by
1309 * the PICT loading code
1311 static int pictCols = 0;
1312 static int pictRows = 0;
1315 * Available graphics modes - 32x32 tiles don't work on Classic
1317 #define GRAF_MODE_NONE 0
1318 #define GRAF_MODE_8X8 1
1319 #define GRAF_MODE_16X16 2
1320 #define GRAF_MODE_32X32 3
1323 * Current and requested graphics modes
1325 static int graf_mode = GRAF_MODE_NONE;
1326 static int graf_mode_req = GRAF_MODE_NONE;
1332 typedef struct FrameRec FrameRec;
1337 * - GWorld for the frame image
1338 * - Handle to pix map (saved for unlocking/locking)
1339 * - Pointer to color pix map (valid only while locked)
1343 GWorldPtr framePort;
1344 PixMapHandle framePixHndl;
1351 * The global picture data
1353 static FrameRec *frameP = NULL;
1359 static void BenSWLockFrame(FrameRec *srcFrameP)
1361 PixMapHandle pixMapH;
1363 pixMapH = GetGWorldPixMap(srcFrameP->framePort);
1364 (void)LockPixels(pixMapH);
1365 HLockHi((Handle)pixMapH);
1366 srcFrameP->framePixHndl = pixMapH;
1367 #if TARGET_API_MAC_CARBON
1368 srcFrameP->framePix = (PixMapPtr)*(Handle)pixMapH;
1370 srcFrameP->framePix = (PixMapPtr)StripAddress(*(Handle)pixMapH);
1379 static void BenSWUnlockFrame(FrameRec *srcFrameP)
1381 if (srcFrameP->framePort != NULL)
1383 HUnlock((Handle)srcFrameP->framePixHndl);
1384 UnlockPixels(srcFrameP->framePixHndl);
1387 srcFrameP->framePix = NULL;
1391 #ifdef MACH_O_CARBON
1394 * Moving graphics resources into data fork -- pelpel
1397 * Given base and type names of a resource, find a file in the
1398 * current application bundle and return its FSSpec in the third argument.
1399 * Returns true on success, false otherwise.
1400 * e.g. get_resource_spec(CFSTR("8x8"), CFSTR("png"), &spec);
1402 static Boolean get_resource_spec(
1403 CFStringRef base_name, CFStringRef type_name, FSSpec *spec)
1408 /* Find resource (=file) in the current bundle */
1409 res_url = CFBundleCopyResourceURL(
1410 CFBundleGetMainBundle(), base_name, type_name, NULL);
1413 if (res_url == NULL) return (false);
1415 /* Convert CFURL to FSRef */
1416 (void)CFURLGetFSRef(res_url, &ref);
1418 /* Convert FSRef to FSSpec */
1419 (void)FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
1421 /* Free allocated CF data */
1431 * Create a off-screen GWorld from contents of a file specified by a FSSpec.
1432 * Based on BenSWCreateGWorldFromPict.
1434 * Globals referenced: data[0], graf_height, graf_width
1435 * Globals updated: pict_rows, pict_cols.
1437 static OSErr create_gworld_from_spec(
1438 GWorldPtr *tile_gw, FSSpec *tile_spec)
1441 GraphicsImportComponent gi;
1442 GWorldPtr gw, tmp_gw;
1443 GDHandle gdh, tmp_gdh;
1447 /* See if QuickTime understands the file format */
1448 err = GetGraphicsImporterForFile(tile_spec, &gi);
1451 if (err != noErr) return (err);
1454 depth = data[0].pixelDepth;
1457 gdh = data[0].theGDH;
1459 /* Retrieve the rect of the image */
1460 err = GraphicsImportGetNaturalBounds(gi, &r);
1462 /* Adjust it, so that the upper left corner becomes (0, 0) */
1463 OffsetRect(&r, -r.left, -r.top);
1465 /* Calculate and set numbers of rows and columns */
1466 pictRows = r.bottom / grafHeight;
1467 pictCols = r.right / grafWidth;
1469 /* Create a GWorld */
1470 err = NewGWorld(&gw, depth, &r, NULL, gdh, noNewDevice);
1473 if (err != noErr) return (err);
1475 /* Save the pointer to the GWorld */
1478 /* Save the current GWorld */
1479 GetGWorld(&tmp_gw, &tmp_gdh);
1481 /* Activate the newly created GWorld */
1482 (void)GraphicsImportSetGWorld(gi, gw, NULL);
1484 /* Prevent pixmap from moving while drawing */
1485 (void)LockPixels(GetGWorldPixMap(gw));
1487 /* Clear the pixels */
1490 /* Draw the image into it */
1491 (void)GraphicsImportDraw(gi);
1493 /* Release the lock*/
1494 UnlockPixels(GetGWorldPixMap(gw));
1496 /* Restore GWorld */
1497 SetGWorld(tmp_gw, tmp_gdh);
1499 /* Close the image importer */
1506 #else /* MACH_O_CARBON */
1508 static OSErr BenSWCreateGWorldFromPict(
1509 GWorldPtr *pictGWorld,
1513 GWorldPtr saveGWorld;
1514 GDHandle saveGDevice;
1515 GWorldPtr tempGWorld;
1524 depth = data[0].pixelDepth;
1527 theGDH = data[0].theGDH;
1529 /* Obtain size rectangle */
1530 pictRect = (**pictH).picFrame;
1531 OffsetRect(&pictRect, -pictRect.left, -pictRect.top);
1533 /* Create a GWorld */
1534 err = NewGWorld(&tempGWorld, depth, &pictRect, nil,
1535 theGDH, noNewDevice);
1544 *pictGWorld = tempGWorld;
1547 GetGWorld(&saveGWorld, &saveGDevice);
1550 SetGWorld(tempGWorld, nil);
1552 /* Dump the pict into the GWorld */
1553 (void)LockPixels(GetGWorldPixMap(tempGWorld));
1554 EraseRect(&pictRect);
1555 DrawPicture(pictH, &pictRect);
1556 UnlockPixels(GetGWorldPixMap(tempGWorld));
1558 /* Restore GWorld */
1559 SetGWorld(saveGWorld, saveGDevice);
1565 #endif /* MACH_O_CARBON */
1569 * Init the global "frameP"
1572 static errr globe_init(void)
1576 GWorldPtr tempPictGWorldP;
1578 #ifdef MACH_O_CARBON
1582 #endif /* MACH_O_CARBON */
1584 /* Use window XXX XXX XXX */
1585 #if TARGET_API_MAC_CARBON
1586 SetPortWindowPort(data[0].w);
1592 #ifdef MACH_O_CARBON
1594 /* Get the tile resources */
1595 if (!get_resource_spec(pictID, CFSTR("png"), &pict_spec)) return (-1);
1598 err = create_gworld_from_spec(&tempPictGWorldP, &pict_spec);
1601 if (err != noErr) return (err);
1603 /* Create the frame */
1604 frameP = (FrameRec*)NewPtrClear((Size)sizeof(FrameRec));
1606 /* Analyze result */
1609 /* Dispose of image GWorld */
1610 DisposeGWorld(tempPictGWorldP);
1612 /* Fake error code */
1617 frameP->framePort = tempPictGWorldP;
1620 BenSWLockFrame(frameP);
1622 #else /* MACH_O_CARBON */
1624 /* Get the pict resource */
1625 newPictH = GetPicture(pictID);
1627 /* Analyze result */
1628 err = (newPictH ? 0 : -1);
1635 err = BenSWCreateGWorldFromPict(&tempPictGWorldP, newPictH);
1637 /* Release resource */
1638 ReleaseResource((Handle)newPictH);
1643 /* Create the frame */
1644 frameP = (FrameRec*)NewPtrClear((Size)sizeof(FrameRec));
1646 /* Analyze result */
1647 err = (frameP ? 0 : -1);
1653 frameP->framePort = tempPictGWorldP;
1656 BenSWLockFrame(frameP);
1660 #endif /* MACH_O_CARBON */
1669 * Nuke the global "frameP"
1671 static errr globe_nuke(void)
1677 BenSWUnlockFrame(frameP);
1679 /* Dispose of the GWorld */
1680 DisposeGWorld(frameP->framePort);
1682 /* Dispose of the memory */
1683 DisposePtr((Ptr)frameP);
1690 FlushEvents(everyEvent, 0);
1697 # ifdef USE_ASYNC_SOUND
1700 * Asynchronous sound player revised
1702 #if defined(USE_QT_SOUND) && !defined(MACH_O_CARBON)
1703 # undef USE_QT_SOUND
1704 #endif /* USE_QT_SOUND && !MACH_O_CARBON */
1708 * Number of channels in the channel pool
1710 #if TARGET_API_MAC_CARBON
1711 #define MAX_CHANNELS 8
1713 #define MAX_CHANNELS 4
1717 * A pool of sound channels
1719 static SndChannelPtr channels[MAX_CHANNELS];
1722 * Status of the channel pool
1724 static Boolean channel_initialised = FALSE;
1727 * Data handles containing sound samples
1729 static SndListHandle samples[SOUND_MAX];
1732 * Reference counts of sound samples
1734 static SInt16 sample_refs[SOUND_MAX];
1740 * These constants aren't used by the program at the moment.
1742 #define SOUND_VOLUME_MIN 0 /* Default minimum sound volume */
1743 #define SOUND_VOLUME_MAX 255 /* Default maximum sound volume */
1744 #define VOLUME_MIN 0 /* Minimum sound volume in % */
1745 #define VOLUME_MAX 100 /* Maximum sound volume in % */
1746 #define VOLUME_INC 5 /* Increment sound volume in % */
1748 /* I'm just too lazy to write a panel for this XXX XXX */
1749 static SInt16 sound_volume = SOUND_VOLUME_MAX;
1754 * QuickTime sound, by Ron Anderson
1756 * I didn't choose to use Windows-style .ini files (Ron wrote a parser
1757 * for it, but...), nor did I use lib/xtra directory, hoping someone
1758 * would code plist-based configuration code in the future -- pelpel
1763 * Load sound effects from data-fork resources. They are wav files
1764 * with the same names as angband_sound_name[] (variable.c)
1766 * Globals referenced: angband_sound_name[]
1767 * Globals updated: samples[] (they can be *huge*)
1769 static void load_sounds(void)
1774 /* Start QuickTime */
1775 err = EnterMovies();
1778 if (err != noErr) return;
1781 * This loop may take a while depending on the count and size of samples
1784 * We should use a progress dialog for this.
1786 for (i = 1; i < SOUND_MAX; i++)
1788 /* Apple APIs always give me headacke :( */
1799 /* Allocate CFString with the name of sound event to be processed */
1800 name = CFStringCreateWithCString(NULL, angband_sound_name[i],
1801 kTextEncodingUS_ASCII);
1804 if (name == NULL) continue;
1806 /* Find sound sample resource with the same name */
1807 res = get_resource_spec(name, CFSTR("wav"), &spec);
1809 /* Free the reference to CFString */
1815 /* Open the sound file */
1816 err = OpenMovieFile(&spec, &file_id, fsRdPerm);
1819 if (err != noErr) continue;
1821 /* Create Movie from the file */
1822 err = NewMovieFromFile(&movie, file_id, &res_id, movie_name,
1823 newMovieActive, NULL);
1826 if (err != noErr) goto close_file;
1828 /* Get the first track of the movie */
1829 track = GetMovieIndTrackType(movie, 1, AudioMediaCharacteristic,
1830 movieTrackCharacteristic | movieTrackEnabledOnly );
1833 if (track == NULL) goto close_movie;
1835 /* Allocate a handle to store sample */
1839 if (h == NULL) goto close_track;
1841 /* Dump the sample into the handle */
1842 err = PutMovieIntoTypedHandle(movie, track, soundListRsrc, h, 0,
1843 GetTrackDuration(track), 0L, NULL);
1848 /* Store the handle in the sample list */
1849 samples[i] = (SndListHandle)h;
1855 /* Free unused handle */
1859 /* Free the track */
1860 close_track: DisposeMovieTrack(track);
1862 /* Free the movie */
1863 close_movie: DisposeMovie(movie);
1865 /* Close the movie file */
1866 close_file: CloseMovieFile(file_id);
1869 /* Stop QuickTime */
1873 #else /* USE_QT_SOUND */
1876 * Return a handle of 'snd ' resource given Angband sound event number,
1877 * or NULL if it isn't found.
1879 * Globals referenced: angband_sound_name[] (variable.c)
1881 static SndListHandle find_sound(int num)
1885 /* Get the proper sound name */
1886 strnfmt((char*)sound + 1, 255, "%.16s.wav", angband_sound_name[num]);
1887 sound[0] = strlen((char*)sound + 1);
1889 /* Obtain resource XXX XXX XXX */
1890 return ((SndListHandle)GetNamedResource('snd ', sound));
1893 #endif /* USE_QT_SOUND */
1897 * Clean up sound support - to be called when the game exits.
1899 * Globals referenced: channels[], samples[], sample_refs[].
1901 static void cleanup_sound(void)
1905 /* No need to clean it up */
1906 if (!channel_initialised) return;
1908 /* Dispose channels */
1909 for (i = 0; i < MAX_CHANNELS; i++)
1911 /* Drain sound commands and free the channel */
1912 SndDisposeChannel(channels[i], TRUE);
1915 /* Free sound data */
1916 for (i = 1; i < SOUND_MAX; i++)
1919 if ((sample_refs[i] > 0) && (samples[i] != NULL))
1922 HUnlock((Handle)samples[i]);
1925 #ifndef USE_QT_SOUND
1928 if (samples[i]) ReleaseResource((Handle)samples[i]);
1932 if (samples[i]) DisposeHandle((Handle)samples[i]);
1933 #endif /* !USE_QT_SOUND */
1939 * Play sound effects asynchronously -- pelpel
1941 * I don't believe those who first started using the previous implementations
1942 * imagined this is *much* more complicated as it may seem. Anyway,
1943 * introduced round-robin scheduling of channels and made it much more
1944 * paranoid about HLock/HUnlock.
1946 * XXX XXX de-refcounting, HUnlock and ReleaseResource should be done
1947 * using channel's callback procedures, which set global flags, and
1948 * a procedure hooked into CheckEvents does housekeeping. On the other
1949 * hand, this lazy reclaiming strategy keeps things simple (no interrupt
1950 * time code) and provides a sort of cache for sound data.
1952 * Globals referenced: channel_initialised, channels[], samples[],
1954 * Globals updated: ditto.
1956 static void play_sound(int num, SInt16 vol)
1965 static int next_chan;
1966 static SInt16 channel_occupants[MAX_CHANNELS];
1967 static SndCommand volume_cmd, quiet_cmd;
1970 /* Initialise sound channels */
1971 if (!channel_initialised)
1973 for (i = 0; i < MAX_CHANNELS; i++)
1975 /* Paranoia - Clear occupant table */
1976 /* channel_occupants[i] = 0; */
1978 /* Create sound channel for all sounds to play from */
1979 err = SndNewChannel(&channels[i], sampledSynth, initMono, 0L);
1987 SndDisposeChannel(channels[i], TRUE);
1991 plog(_("サウンドチャンネルを初期化出来ません!", "Cannot initialise sound channels!"));
1993 /* Cancel request */
1994 use_sound = arg_sound = FALSE;
2001 /* First channel to use */
2004 /* Prepare volume command */
2005 volume_cmd.cmd = volumeCmd;
2006 volume_cmd.param1 = 0;
2007 volume_cmd.param2 = 0;
2009 /* Prepare quiet command */
2010 quiet_cmd.cmd = quietCmd;
2011 quiet_cmd.param1 = 0;
2012 quiet_cmd.param2 = 0;
2014 /* Initialisation complete */
2015 channel_initialised = TRUE;
2019 if ((num <= 0) || (num >= SOUND_MAX)) return;
2021 /* Prepare volume command */
2022 volume_cmd.param2 = ((SInt32)vol << 16) | vol;
2024 /* Channel to use (round robin) */
2025 chan = channels[next_chan];
2027 /* See if the resource is already in use */
2028 if (sample_refs[num] > 0)
2030 /* Resource in use */
2033 /* Increase the refcount */
2037 /* Sound is not currently in use */
2040 /* Get handle for the sound */
2044 h = find_sound(num);
2045 #endif /* USE_QT_SOUND */
2047 /* Sample not available */
2048 if (h == NULL) return;
2050 #ifndef USE_QT_SOUND
2053 LoadResource((Handle)h);
2058 #endif /* !USE_QT_SOUND */
2060 /* Lock the handle */
2063 /* Initialise refcount */
2064 sample_refs[num] = 1;
2067 /* Poll the channel */
2068 err = SndChannelStatus(chan, sizeof(SCStatus), &status);
2070 /* It isn't available */
2071 if ((err != noErr) || status.scChannelBusy)
2074 SndDoImmediate(chan, &quiet_cmd);
2077 /* Previously played sound on this channel */
2078 prev_num = channel_occupants[next_chan];
2080 /* Process previously played sound */
2083 /* Decrease refcount */
2084 sample_refs[prev_num]--;
2086 /* We can free it now */
2087 if (sample_refs[prev_num] <= 0)
2090 HUnlock((Handle)samples[prev_num]);
2092 #ifndef USE_QT_SOUND
2095 ReleaseResource((Handle)samples[prev_num]);
2098 samples[prev_num] = NULL;
2100 #endif /* !USE_QT_SOUND */
2103 sample_refs[prev_num] = 0;
2107 /* Remember this sound as the current occupant of the channel */
2108 channel_occupants[next_chan] = num;
2110 /* Set up volume for channel */
2111 SndDoImmediate(chan, &volume_cmd);
2113 /* Play new sound asynchronously */
2114 SndPlay(chan, h, TRUE);
2116 /* Schedule next channel (round robin) */
2118 if (next_chan >= MAX_CHANNELS) next_chan = 0;
2121 # else /* USE_ASYNC_SOUND */
2124 * Play sound synchronously
2126 * This may not be your choice, but much safer and much less resource hungry.
2128 static void play_sound(int num, SInt16 vol)
2133 /* Get the proper sound name */
2134 strnfmt((char*)sound + 1, 255, "%.16s.wav", angband_sound_name[num]);
2135 sound[0] = strlen((char*)sound + 1);
2137 /* Obtain resource XXX XXX XXX */
2138 handle = GetNamedResource('snd ', sound);
2141 if (handle == NULL) return;
2144 LoadResource(handle);
2147 /* Play sound (wait for completion) */
2148 SndPlay(NULL, (SndListHandle)handle, FALSE);
2150 /* Unlock and release */
2152 ReleaseResource(handle);
2155 # endif /* USE_ASYNC_SOUND */
2162 static short soundmode[8];
2165 #define SND_ATTACK 1
2170 #define SND_CMD_ERROR 6
2172 #ifndef MACH_O_CARBON
2174 static int soundchoice[] = {
2242 static int ext_sound = 0;
2243 static int ext_graf = 0;
2245 #endif /* !MACH_O_CARBON */
2247 #endif /* ANGBAND_LITE_MAC */
2251 /*** Support for the "z-term.c" package ***/
2255 * Initialize a new Term
2257 * Note also the "window type" called "noGrowDocProc", which might be more
2258 * appropriate for the main "screen" window.
2260 * Note the use of "srcCopy" mode for optimized screen writes.
2262 static void Term_init_mac(term *t)
2264 term_data *td = (term_data*)(t->data);
2266 static RGBColor black = {0x0000,0x0000,0x0000};
2267 static RGBColor white = {0xFFFF,0xFFFF,0xFFFF};
2269 #ifdef ANGBAND_LITE_MAC
2271 /* Make the window */
2272 td->w = NewWindow(0, &td->r, td->title, 0, noGrowDocProc, (WindowPtr)-1, 1, 0L);
2274 #else /* ANGBAND_LITE_MAC */
2276 /* Make the window */
2277 td->w = NewCWindow(0, &td->r, td->title, 0, documentProc, (WindowPtr)-1, 1, 0L);
2279 #endif /* ANGBAND_LITE_MAC */
2281 /* Activate the window */
2284 /* Erase behind words */
2287 /* Apply and Verify */
2288 term_data_check_font(td);
2289 term_data_check_size(td);
2291 /* Resize the window */
2292 term_data_resize(td);
2294 #ifdef ANGBAND_LITE_MAC
2296 /* Prepare the colors (base colors) */
2297 BackColor(blackColor);
2298 ForeColor(whiteColor);
2300 #else /* ANGBAND_LITE_MAC */
2302 /* Prepare the colors (real colors) */
2303 RGBBackColor(&black);
2304 RGBForeColor(&white);
2310 GDHandle currentGDH;
2311 GWorldPtr windowGWorld;
2312 PixMapHandle basePixMap;
2314 /* Obtain the rect */
2315 #if TARGET_API_MAC_CARBON
2316 GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &globalRect );
2318 globalRect = td->w->portRect;
2319 LocalToGlobal((Point*)&globalRect.top);
2320 LocalToGlobal((Point*)&globalRect.bottom);
2323 /* Obtain the proper GDH */
2324 mainGDH = GetMaxDevice(&globalRect);
2326 /* Extract GWorld and GDH */
2327 GetGWorld(&windowGWorld, ¤tGDH);
2329 /* Obtain base pixmap */
2330 basePixMap = (**mainGDH).gdPMap;
2332 /* Save pixel depth */
2333 td->pixelDepth = (**basePixMap).pixelSize;
2335 /* Save Window GWorld */
2336 td->theGWorld = windowGWorld;
2338 /* Save Window GDH */
2339 td->theGDH = currentGDH;
2342 td->mainSWGDH = mainGDH;
2345 #endif /* ANGBAND_LITE_MAC */
2350 #if TARGET_API_MAC_CARBON
2351 GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &portRect );
2352 global_to_local( &portRect );
2354 portRect = td->w->portRect;
2356 /* Clip to the window */
2357 ClipRect(&portRect);
2359 /* Erase the window */
2360 EraseRect(&portRect);
2362 /* Invalidate the window */
2363 #if TARGET_API_MAC_CARBON
2364 InvalWindowRect((WindowRef)(td->w), (const Rect *)(&portRect));
2366 InvalRect(&portRect);
2369 /* Display the window if needed */
2370 if (td->mapped) ShowWindow(td->w);
2372 /* Hack -- set "mapped" flag */
2373 t->mapped_flag = td->mapped;
2379 /* if (err == noErr)
2390 static void Term_nuke_mac(term *t)
2403 static errr Term_user_mac(int n)
2417 static errr Term_xtra_mac_react(void)
2419 term_data *td = (term_data*)(Term->data);
2425 #ifdef ANGBAND_LITE_MAC
2429 #else /* ANGBAND_LITE_MAC */
2432 if (use_sound != arg_sound)
2435 use_sound = arg_sound;
2439 /* Handle graphics */
2440 if (graf_mode_req != graf_mode)
2442 /* dispose old GWorld's if present */
2445 /* Setup parameters according to request */
2446 switch (graf_mode_req)
2448 /* ASCII - no graphics whatsoever */
2449 case GRAF_MODE_NONE:
2451 use_graphics = arg_graphics = GRAPHICS_NONE;
2456 * 8x8 tiles (PICT id 1001)
2457 * no transparency effect
2458 * "old" graphics definitions
2462 use_graphics = arg_graphics = GRAPHICS_ORIGINAL;
2463 ANGBAND_GRAF = "old";
2464 #ifdef MACH_O_CARBON
2465 pictID = CFSTR("8x8");
2468 #endif /* MACH_O_CARBON */
2469 grafWidth = grafHeight = 8;
2474 * 16x16 tiles (images: PICT id 1002)
2475 * with transparency effect
2476 * "new" graphics definitions
2478 case GRAF_MODE_16X16:
2480 use_graphics = arg_graphics = GRAPHICS_ADAM_BOLT;
2481 ANGBAND_GRAF = "new";
2482 #ifdef MACH_O_CARBON
2483 pictID = CFSTR("16x16");
2486 #endif /* MACH_O_CARBON */
2487 grafWidth = grafHeight = 16;
2492 if ((graf_mode_req != GRAF_MODE_NONE) && !frameP && (globe_init() != 0))
2494 plog(_("グラフィックの初期化は出来ませんでした.", "Cannot initialize graphics!"));
2496 /* reject request */
2497 graf_mode_req = GRAF_MODE_NONE;
2499 /* reset graphics flags */
2500 use_graphics = arg_graphics = FALSE;
2504 /* update current graphics mode */
2505 graf_mode = graf_mode_req;
2507 /* Apply and Verify */
2508 term_data_check_size(td);
2510 /* Resize the window */
2511 term_data_resize(td);
2517 #endif /* ANGBAND_LITE_MAC */
2525 * Do a "special thing"
2527 static errr Term_xtra_mac(int n, int v)
2529 term_data *td = (term_data*)(Term->data);
2537 case TERM_XTRA_NOISE:
2546 #ifdef ANGBAND_LITE_MAC
2550 #else /* ANGBAND_LITE_MAC */
2553 case TERM_XTRA_SOUND:
2556 play_sound(v, sound_volume);
2562 #endif /* ANGBAND_LITE_MAC */
2564 /* Process random events */
2565 case TERM_XTRA_BORED:
2567 /* Process an event */
2568 (void)CheckEvents(FALSE);
2574 /* Process pending events */
2575 case TERM_XTRA_EVENT:
2577 /* Process an event */
2578 (void)CheckEvents(v);
2584 /* Flush all pending events (if any) */
2585 case TERM_XTRA_FLUSH:
2587 /* Hack -- flush all events */
2588 while (CheckEvents(TRUE)) /* loop */;
2594 /* Hack -- Change the "soft level" */
2595 case TERM_XTRA_LEVEL:
2597 /* Activate if requested */
2598 if (v) activate(td->w);
2604 /* Clear the screen */
2605 case TERM_XTRA_CLEAR:
2609 #if TARGET_API_MAC_CARBON
2610 GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &portRect );
2611 global_to_local( &portRect );
2613 portRect = td->w->portRect;
2616 /* No clipping XXX XXX XXX */
2617 ClipRect(&portRect);
2619 /* Erase the window */
2620 EraseRect(&portRect);
2623 term_data_color(td, TERM_WHITE);
2625 /* Frame the window in white */
2627 LineTo(0, td->size_hgt-1);
2628 LineTo(td->size_wid-1, td->size_hgt-1);
2629 LineTo(td->size_wid-1, 0);
2631 /* Clip to the new size */
2632 r.left = portRect.left + td->size_ow1;
2633 r.top = portRect.top + td->size_oh1;
2634 r.right = portRect.right - td->size_ow2;
2635 r.bottom = portRect.bottom - td->size_oh2;
2642 /* React to changes */
2643 case TERM_XTRA_REACT:
2645 /* React to changes */
2646 return (Term_xtra_mac_react());
2649 /* Delay (milliseconds) */
2650 case TERM_XTRA_DELAY:
2655 #if TARGET_API_MAC_CARBON
2659 /* Convert millisecs to ticks */
2660 ticks = (v * 60L) / 1000;
2663 * Hack? - Put the programme into sleep.
2664 * No events match ~everyEvent, so nothing
2665 * should be lost in Angband's event queue.
2666 * Even if ticks are 0, it's worth calling for
2667 * the above mentioned reasons.
2669 WaitNextEvent((EventMask)~everyEvent, &tmp, ticks, nil);
2671 long m = TickCount() + (v * 60L) / 1000;
2674 while (TickCount() < m) /* loop */;
2690 * Low level graphics (Assumes valid input).
2691 * Draw a "cursor" at (x,y), using a "yellow box".
2692 * We are allowed to use "Term_grab()" to determine
2693 * the current screen contents (for inverting, etc).
2695 static errr Term_curs_mac(int x, int y)
2699 term_data *td = (term_data*)(Term->data);
2702 term_data_color(td, TERM_YELLOW);
2704 /* Frame the grid */
2705 r.left = x * td->tile_wid + td->size_ow1;
2706 r.right = r.left + td->tile_wid;
2707 r.top = y * td->tile_hgt + td->size_oh1;
2708 r.bottom = r.top + td->tile_hgt;
2718 * Low level graphics (Assumes valid input).
2719 * Draw a "big cursor" at (x,y), using a "yellow box".
2720 * We are allowed to use "Term_grab()" to determine
2721 * the current screen contents (for inverting, etc).
2723 static errr Term_bigcurs_mac(int x, int y)
2727 term_data *td = (term_data*)(Term->data);
2730 term_data_color(td, TERM_YELLOW);
2732 /* Frame the grid */
2733 r.left = x * td->tile_wid + td->size_ow1;
2734 r.right = r.left + 2 * td->tile_wid;
2735 r.top = y * td->tile_hgt + td->size_oh1;
2736 r.bottom = r.top + td->tile_hgt;
2746 * Low level graphics (Assumes valid input)
2748 * Erase "n" characters starting at (x,y)
2750 static errr Term_wipe_mac(int x, int y, int n)
2754 term_data *td = (term_data*)(Term->data);
2756 /* Erase the block of characters */
2757 r.left = x * td->tile_wid + td->size_ow1;
2758 r.right = r.left + n * td->tile_wid;
2759 r.top = y * td->tile_hgt + td->size_oh1;
2760 r.bottom = r.top + td->tile_hgt;
2769 * Low level graphics. Assumes valid input.
2771 * Draw several ("n") chars, with an attr, at a given location.
2773 static errr Term_text_mac(int x, int y, int n, byte a, const char *cp)
2777 term_data *td = (term_data*)(Term->data);
2780 term_data_color(td, (a & 0x0F));
2782 /* Starting pixel */
2783 xp = x * td->tile_wid + td->tile_o_x + td->size_ow1;
2784 yp = y * td->tile_hgt + td->tile_o_y + td->size_oh1;
2786 /* Move to the correct location */
2789 /* Draw the character */
2790 if (n == 1) DrawChar(*cp);
2792 /* Draw the string */
2793 else DrawText(cp, 0, n);
2801 * Low level graphics (Assumes valid input)
2803 * Erase "n" characters starting at (x,y)
2805 static errr Term_pict_mac(int x, int y, int n, const byte *ap, const char *cp,
2806 const byte *tap, const char *tcp)
2810 term_data *td = (term_data*)(Term->data);
2811 GDHandle saveGDevice;
2812 GWorldPtr saveGWorld;
2815 GetGWorld(&saveGWorld, &saveGDevice);
2817 r2.left = x * td->tile_wid + td->size_ow1;
2818 r2.right = r2.left + td->tile_wid;
2819 r2.top = y * td->tile_hgt + td->size_oh1;
2820 r2.bottom = r2.top + td->tile_hgt;
2824 /* Instantiate font */
2825 TextFont(td->font_id);
2826 TextSize(td->font_size);
2827 TextFace(td->font_face);
2829 /* Restore colors */
2830 BackColor(blackColor);
2831 ForeColor(whiteColor);
2835 /* Destination rectangle */
2836 /* r2.left = x * td->tile_wid + td->size_ow1;
2837 r2.top = y * td->tile_hgt + td->size_oh1;
2838 r2.bottom = r2.top + td->tile_hgt;*/
2842 /* Scan the input */
2843 for (i = 0; i < n; i++)
2850 /* Second byte of bigtile */
2851 if (use_bigtile && a == 255)
2854 r2.left += td->tile_wid;
2859 /* Prepare right of rectangle now */
2860 r2.right = r2.left + td->tile_wid;
2862 #ifdef ANGBAND_LITE_MAC
2866 #else /* ANGBAND_LITE_MAC */
2868 /* Graphics -- if Available and Needed */
2869 if (use_graphics && ((byte)a & 0x80) && ((byte)c & 0x80))
2871 #if TARGET_API_MAC_CARBON
2872 PixMapHandle srcBitMap = GetGWorldPixMap(frameP->framePort);
2873 PixMapHandle destBitMap;
2875 BitMapPtr srcBitMap = (BitMapPtr)(frameP->framePix);
2876 BitMapPtr destBitMap;
2883 bool terrain_flag = FALSE;
2887 if ((a != ta || c != tc) &&
2888 ((byte)ta & 0x80) && ((byte)tc & 0x80))
2891 row = ((byte)ta & 0x7F);
2892 col = ((byte)tc & 0x7F);
2894 /* Terrain Source rectangle */
2895 terrain_r.left = col * grafWidth;
2896 terrain_r.top = row * grafHeight;
2897 terrain_r.right = terrain_r.left + grafWidth;
2898 terrain_r.bottom = terrain_r.top + grafHeight;
2900 terrain_flag = TRUE;
2904 row = ((byte)a & 0x7F);
2905 col = ((byte)c & 0x7F);
2907 /* Source rectangle */
2908 r1.left = col * grafWidth;
2909 r1.top = row * grafHeight;
2910 r1.right = r1.left + grafWidth;
2911 r1.bottom = r1.top + grafHeight;
2913 /* Hardwire CopyBits */
2914 BackColor(whiteColor);
2915 ForeColor(blackColor);
2917 /* Draw the picture */
2918 #if TARGET_API_MAC_CARBON
2919 destBitMap = GetPortPixMap(GetWindowPort( td->w ));
2921 destBitMap = (BitMapPtr)&(td->w->portBits);
2923 if (use_bigtile) r2.right += td->tile_wid;
2928 * Source mode const = srcCopy:
2930 * determine how close the color of the source
2931 * pixel is to black, and assign this relative
2932 * amount of foreground color to the
2933 * destination pixel; determine how close the
2934 * color of the source pixel is to white, and
2935 * assign this relative amount of background
2936 * color to the destination pixel
2938 #if TARGET_API_MAC_CARBON
2939 CopyBits( (BitMap *) *srcBitMap, (BitMap *) *destBitMap, &terrain_r, &r2, srcCopy, NULL);
2941 CopyBits( srcBitMap, destBitMap, &terrain_r, &r2, srcCopy, NULL );
2944 * Draw transparent tile
2945 * BackColor is ignored and the destination is
2948 BackColor(blackColor);
2949 #if TARGET_API_MAC_CARBON
2950 CopyBits( (BitMap *) *srcBitMap, (BitMap *) *destBitMap, &r1, &r2, transparent, NULL);
2952 CopyBits( srcBitMap, destBitMap, &r1, &r2, transparent, NULL );
2957 #if TARGET_API_MAC_CARBON
2958 CopyBits( (BitMap *) *srcBitMap, (BitMap *) *destBitMap, &r1, &r2, srcCopy, NULL);
2960 CopyBits( srcBitMap, destBitMap, &r1, &r2, srcCopy, NULL );
2964 /* Restore colors */
2965 BackColor(blackColor);
2966 ForeColor(whiteColor);
2975 #endif /* ANGBAND_LITE_MAC */
2983 term_data_color(td, (a & 0x0F));
2985 /* Starting pixel */
2986 xp = r2.left + td->tile_o_x;
2987 yp = r2.top + td->tile_o_y;
2989 /* Move to the correct location */
2995 /* Double width rectangle */
2996 r2.right += td->tile_wid;
3001 /* Draw the character */
3006 r2.left += td->tile_wid;
3014 /* Draw the character */
3020 r2.left += td->tile_wid;
3029 * Create and initialize window number "i"
3031 static void term_data_link(int i)
3035 term_data *td = &data[i];
3040 /* Require mapped */
3041 if (!td->mapped) return;
3046 /* Initialize the term */
3047 term_init(td->t, td->cols, td->rows, td->keys);
3049 /* Use a "software" cursor */
3050 td->t->soft_cursor = TRUE;
3052 /* Erase with "white space" */
3053 td->t->attr_blank = TERM_WHITE;
3054 td->t->char_blank = ' ';
3056 /* Prepare the init/nuke hooks */
3057 td->t->init_hook = Term_init_mac;
3058 td->t->nuke_hook = Term_nuke_mac;
3060 /* Prepare the function hooks */
3061 td->t->user_hook = Term_user_mac;
3062 td->t->xtra_hook = Term_xtra_mac;
3063 td->t->wipe_hook = Term_wipe_mac;
3064 td->t->curs_hook = Term_curs_mac;
3065 td->t->bigcurs_hook = Term_bigcurs_mac;
3066 td->t->text_hook = Term_text_mac;
3067 td->t->pict_hook = Term_pict_mac;
3069 /* Link the local structure */
3070 td->t->data = (vptr)(td);
3073 Term_activate(td->t);
3075 /* Global pointer */
3076 angband_term[i] = td->t;
3084 #ifdef MACH_O_CARBON
3088 * Return a POSIX pathname of the lib directory, or NULL if it can't be
3089 * located. Caller must supply a buffer along with its size in bytes,
3090 * where returned pathname will be stored.
3091 * I prefer use of goto's to several nested if's, if they involve error
3092 * handling. Sorry if you are offended by their presence. Modern
3093 * languages have neater constructs for this kind of jobs -- pelpel
3095 static char *locate_lib(char *buf, size_t size)
3097 CFURLRef main_url = NULL;
3098 CFStringRef main_str = NULL;
3102 /* Obtain the URL of the main bundle */
3103 main_url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
3106 if (main_url == NULL) goto ret;
3108 /* Convert it to POSIX pathname */
3109 main_str = CFURLCopyFileSystemPath(main_url, kCFURLPOSIXPathStyle);
3112 if (main_str == NULL) goto ret;
3114 /* Convert it again from darn unisomething encoding to ASCII */
3115 if (CFStringGetCString(main_str, buf, size, kTextEncodingUS_ASCII) == FALSE)
3118 /* Find the last '/' in the pathname */
3119 p = strrchr(buf, '/');
3121 /* Paranoia - cannot happen */
3122 if (p == NULL) goto ret;
3124 /* Remove the trailing path */
3128 * Paranoia - bounds check, with 5 being the length of "/lib/"
3129 * and 1 for terminating '\0'.
3131 if (strlen(buf) + 5 + 1 > size) goto ret;
3133 /* Append "/lib/" */
3134 strcat(buf, "/lib/");
3141 /* Release objects allocated and implicitly retained by the program */
3142 if (main_str) CFRelease(main_str);
3143 if (main_url) CFRelease(main_url);
3145 /* pathname of the lib folder or NULL */
3150 #else /* MACH_O_CARBON */
3154 * Set the "current working directory" (also known as the "default"
3155 * volume/directory) to the location of the current application.
3157 * Code by: Maarten Hazewinkel (mmhazewi@cs.ruu.nl)
3159 * This function does not appear to work correctly with System 6.
3161 static void SetupAppDir(void)
3165 char errString[100];
3167 /* Get the location of the Angband executable */
3168 fcbBlock.ioCompletion = NULL;
3169 fcbBlock.ioNamePtr = NULL;
3170 fcbBlock.ioVRefNum = 0;
3171 fcbBlock.ioRefNum = CurResFile();
3172 fcbBlock.ioFCBIndx = 0;
3173 err = PBGetFCBInfo(&fcbBlock, FALSE);
3176 sprintf(errString, _("PBGetFCBInfo エラー #%d.\r 終了します.", "Fatal PBGetFCBInfo Error #%d.\r Exiting."), err);
3177 mac_warning(errString);
3181 /* Extract the Vol and Dir */
3182 app_vol = fcbBlock.ioFCBVRefNum;
3183 app_dir = fcbBlock.ioFCBParID;
3185 /* Set the current working directory to that location */
3186 err = HSetVol(NULL, app_vol, app_dir);
3189 sprintf(errString, _("HSetVol エラー #%d.\r 終了します.", "Fatal HSetVol Error #%d.\r Exiting."), err);
3190 mac_warning(errString);
3199 #if TARGET_API_MAC_CARBON
3201 * Using Core Foundation's Preferences services -- pelpel
3203 * Requires OS 8.6 or greater with CarbonLib 1.1 or greater. Or OS X,
3206 * Without this, we can support older versions of OS 8 as well
3207 * (with CarbonLib 1.0.4).
3209 * Frequent allocation/deallocation of small chunks of data is
3210 * far from my liking, but since this is only called at the
3211 * beginning and the end of a session, I hope this hardly matters.
3216 * Store "value" as the value for preferences item name
3219 static void save_pref_short(const char *key, short value)
3222 CFNumberRef cf_value;
3224 /* allocate and initialise the key */
3225 cf_key = CFStringCreateWithCString(NULL, key, kTextEncodingUS_ASCII);
3227 /* allocate and initialise the value */
3228 cf_value = CFNumberCreate(NULL, kCFNumberShortType, &value);
3230 if ((cf_key != NULL) && (cf_value != NULL))
3232 /* Store the key-value pair in the applications preferences */
3233 CFPreferencesSetAppValue(
3236 kCFPreferencesCurrentApplication);
3240 * Free CF data - the reverse order is a vain attempt to
3241 * minimise memory fragmentation.
3243 if (cf_value) CFRelease(cf_value);
3244 if (cf_key) CFRelease(cf_key);
3249 * Load preference value for key, returns TRUE if it succeeds with
3250 * vptr updated appropriately, FALSE otherwise.
3252 static bool query_load_pref_short(const char *key, short *vptr)
3255 CFNumberRef cf_value;
3257 /* allocate and initialise the key */
3258 cf_key = CFStringCreateWithCString(NULL, key, kTextEncodingUS_ASCII);
3261 if (cf_key == NULL) return (FALSE);
3263 /* Retrieve value for the key */
3264 cf_value = CFPreferencesCopyAppValue(
3266 kCFPreferencesCurrentApplication);
3268 /* Value not found */
3269 if (cf_value == NULL)
3275 /* Convert the value to short */
3282 CFRelease(cf_value);
3291 * Update short data pointed by vptr only if preferences
3292 * value for key is located.
3294 static void load_pref_short(const char *key, short *vptr)
3298 if (query_load_pref_short(key, &tmp)) *vptr = tmp;
3304 * Save preferences to preferences file for current host+current user+
3305 * current application.
3307 static void cf_save_prefs()
3312 save_pref_short("version.major", FAKE_VERSION);
3313 save_pref_short("version.minor", FAKE_VER_MAJOR);
3314 save_pref_short("version.patch", FAKE_VER_MINOR);
3315 save_pref_short("version.extra", FAKE_VER_PATCH);
3318 save_pref_short("arg.arg_sound", arg_sound);
3319 save_pref_short("arg.graf_mode", graf_mode);
3320 save_pref_short("arg.arg_bigtile", arg_bigtile);
3322 #ifndef MACH_O_CARBON
3324 for( i = 0 ; i < 7 ; i++ )
3325 save_pref_short(format("sound%d.on", i), soundmode[i]);
3326 #endif /* MACH_O_CARBON */
3329 for (i = 0; i < MAX_TERM_DATA; i++)
3331 term_data *td = &data[i];
3333 save_pref_short(format("term%d.mapped", i), td->mapped);
3335 save_pref_short(format("term%d.font_id", i), td->font_id);
3336 save_pref_short(format("term%d.font_size", i), td->font_size);
3337 save_pref_short(format("term%d.font_face", i), td->font_face);
3339 save_pref_short(format("term%d.tile_wid", i), td->tile_wid);
3340 save_pref_short(format("term%d.tile_hgt", i), td->tile_hgt);
3342 save_pref_short(format("term%d.cols", i), td->cols);
3343 save_pref_short(format("term%d.rows", i), td->rows);
3344 save_pref_short(format("term%d.left", i), td->r.left);
3345 save_pref_short(format("term%d.top", i), td->r.top);
3349 * Make sure preferences are persistent
3351 CFPreferencesAppSynchronize(
3352 kCFPreferencesCurrentApplication);
3357 * Load preferences from preferences file for current host+current user+
3358 * current application.
3360 static void cf_load_prefs()
3363 short pref_major, pref_minor, pref_patch, pref_extra;
3366 /* Assume nothing is wrong, yet */
3369 /* Load version information */
3370 ok &= query_load_pref_short("version.major", &pref_major);
3371 ok &= query_load_pref_short("version.minor", &pref_minor);
3372 ok &= query_load_pref_short("version.patch", &pref_patch);
3373 ok &= query_load_pref_short("version.extra", &pref_extra);
3375 /* Any of the above failed */
3378 /* This may be the first run */
3379 mac_warning(_("初期設定ファイルが見つかりません。", "Preferences are not found."));
3381 /* Ignore the rest */
3390 if (query_load_pref_short("arg.arg_sound", &pref_tmp))
3391 arg_sound = pref_tmp;
3394 if (query_load_pref_short("arg.graf_mode", &pref_tmp))
3395 graf_mode_req = pref_tmp;
3397 /* double-width tiles */
3398 if (query_load_pref_short("arg.arg_bigtile", &pref_tmp))
3400 arg_bigtile = use_bigtile = pref_tmp;
3405 #ifndef MACH_O_CARBON
3407 for( i = 0 ; i < 7 ; i++ )
3409 query_load_pref_short(format("sound%d.on", i), &soundmode[i]);
3411 #endif /* MACH_O_CARBON */
3414 for (i = 0; i < MAX_TERM_DATA; i++)
3416 term_data *td = &data[i];
3418 load_pref_short(format("term%d.mapped", i), &td->mapped);
3420 load_pref_short(format("term%d.font_id", i), &td->font_id);
3421 load_pref_short(format("term%d.font_size", i), &td->font_size);
3422 load_pref_short(format("term%d.font_face", i), &td->font_face);
3424 load_pref_short(format("term%d.tile_wid", i), &td->tile_wid);
3425 load_pref_short(format("term%d.tile_hgt", i), &td->tile_hgt);
3427 load_pref_short(format("term%d.cols", i), &td->cols);
3428 load_pref_short(format("term%d.rows", i), &td->rows);
3429 load_pref_short(format("term%d.left", i), &td->r.left);
3430 load_pref_short(format("term%d.top", i), &td->r.top);
3436 * Global "preference" file pointer
3441 * Read a "short" from the file
3443 static int getshort(void)
3447 if (0 == my_fgets(fff, buf, sizeof(buf))) x = atoi(buf);
3452 * Dump a "short" to the file
3454 static void putshort(int x)
3456 fprintf(fff, "%d\n", x);
3462 * Write the "preference" data to the current "file"
3464 static void save_prefs(void)
3471 /*** The current version ***/
3473 putshort(FAKE_VERSION);
3474 putshort(FAKE_VER_MAJOR);
3475 putshort(FAKE_VER_MINOR);
3476 putshort(FAKE_VER_PATCH);
3478 putshort(arg_sound);
3479 putshort(graf_mode);
3480 putshort(arg_bigtile);
3483 for( i = 0 ; i < 7 ; i++ )
3484 putshort(soundmode[i]);
3487 for (i = 0; i < MAX_TERM_DATA; i++)
3492 putshort(td->mapped);
3494 putshort(td->font_id);
3495 putshort(td->font_size);
3496 putshort(td->font_face);
3498 putshort(td->tile_wid);
3499 putshort(td->tile_hgt);
3504 putshort(td->r.left);
3505 putshort(td->r.top);
3511 * Load the preferences from the current "file"
3513 * XXX XXX XXX Being able to undefine various windows is
3514 * slightly bizarre, and may cause problems.
3516 static void load_prefs(void)
3520 int old_version, old_major, old_minor, old_patch;
3525 /*** Version information ***/
3527 /* Preferences version */
3528 old_version = getshort();
3529 old_major = getshort();
3530 old_minor = getshort();
3531 old_patch = getshort();
3533 /* Hack -- Verify or ignore */
3534 if ((old_version != FAKE_VERSION) ||
3535 (old_major != FAKE_VER_MAJOR) ||
3536 (old_minor != FAKE_VER_MINOR) ||
3537 (old_patch != FAKE_VER_PATCH))
3541 mac_warning("古い初期設定ファイルを無視します.");
3543 mac_warning("Ignoring old preferences.");
3549 arg_sound = getshort();
3550 graf_mode_req = getshort();
3551 arg_bigtile = getshort();
3552 use_bigtile = arg_bigtile;
3555 for( i = 0 ; i < 7 ; i++ )
3556 soundmode[i] = getshort();
3559 for (i = 0; i < MAX_TERM_DATA; i++)
3564 td->mapped = getshort();
3566 td->font_id = getshort();
3567 td->font_size = getshort();
3568 td->font_face = getshort();
3570 td->tile_wid = getshort();
3571 td->tile_hgt = getshort();
3573 td->cols = getshort();
3574 td->rows = getshort();
3576 td->r.left = getshort();
3577 td->r.top = getshort();
3580 if (feof(fff)) break;
3583 #endif /* TARGET_API_MAC_CARBON */
3588 * Hack -- default data for a window
3590 static void term_data_hack(term_data *td)
3594 #if TARGET_API_MAC_CARBON
3596 /* Default to Osaka font (Japanese) */
3597 fid = FMGetFontFamilyFromName( "\pOsaka−等幅" );
3599 /* Default to Monaco font */
3600 fid = FMGetFontFamilyFromName("\pmonaco");
3604 /* Default to 等幅明朝 font (Japanese) */
3605 GetFNum( "\p等幅明朝", &fid);
3606 SetFScaleDisable( true );
3608 /* Default to Monaco font */
3609 GetFNum("\pmonaco", &fid);
3614 WIPE(td, term_data);
3619 /* Default borders */
3630 /* Default font size */
3633 /* Default font face */
3640 /* Default position */
3650 * Read the preference file, Create the windows.
3652 * We attempt to use "FindFolder()" to track down the preference file,
3653 * but if this fails, for any reason, we will try the "SysEnvirons()"
3654 * method, which may work better with System 6.
3656 static void init_windows(void)
3662 #if !TARGET_API_MAC_CARBON
3670 #endif /* !TARGET_API_MAC_CARBON */
3673 /*** Default values ***/
3675 /* Initialize (backwards) */
3676 for (i = MAX_TERM_DATA - 1; i >= 0; i--)
3689 s = angband_term_name[i];
3694 /* Maximal length */
3697 /* Copy the title */
3698 strncpy((char*)(td->title) + 1, s, n);
3700 /* Save the length */
3703 /* Tile the windows */
3704 td->r.left += (b * 30);
3705 td->r.top += (b * 30);
3712 /*** Load preferences ***/
3714 #if TARGET_API_MAC_CARBON
3717 /* Assume failure */
3720 /* Assume failure */
3733 /* Find the folder */
3734 err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
3740 /* Extract a path name */
3741 PathNameFromDirID(dirID, vref, (StringPtr)foo);
3743 /* Convert the string */
3744 ptocstr((StringPtr)foo);
3746 /* Append the preference file name */
3747 strcat(foo, PREF_FILE_NAME);
3749 /* Open the preference file */
3750 fff = fopen(foo, "r");
3757 #endif /* USE_SFL_CODE */
3763 HGetVol(0, &savev, &saved);
3765 /* Go to the "system" folder */
3766 SysEnvirons(curSysEnvVers, &env);
3767 SetVol(0, env.sysVRefNum);
3770 fff = fopen(PREF_FILE_NAME, "r");
3773 HSetVol(0, savev, saved);
3776 /* Load preferences */
3779 /* Load a real preference file */
3782 /* Close the file */
3785 #endif /* TARGET_API_MAC_CARBON */
3788 /*** Instantiate ***/
3799 /* Link (backwards, for stacking order) */
3800 for (i = MAX_TERM_DATA - 1; i >= 0; i--)
3809 Term_activate(td->t);
3812 #ifndef MACH_O_CARBON
3814 static void init_sound( void )
3818 SignedByte permission = fsRdPerm;
3824 /* Descend into "lib" folder */
3825 pb.dirInfo.ioCompletion = NULL;
3826 pb.dirInfo.ioNamePtr = "\plib";
3827 pb.dirInfo.ioVRefNum = app_vol;
3828 pb.dirInfo.ioDrDirID = app_dir;
3829 pb.dirInfo.ioFDirIndex = 0;
3831 /* Check for errors */
3832 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3835 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3837 /* Descend into "lib/save" folder */
3838 pb.dirInfo.ioCompletion = NULL;
3839 pb.dirInfo.ioNamePtr = "\pxtra";
3840 pb.dirInfo.ioVRefNum = app_vol;
3841 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3842 pb.dirInfo.ioFDirIndex = 0;
3844 /* Check for errors */
3845 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3848 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3850 /* Descend into "lib/save" folder */
3851 pb.dirInfo.ioCompletion = NULL;
3852 pb.dirInfo.ioNamePtr = "\psound";
3853 pb.dirInfo.ioVRefNum = app_vol;
3854 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3855 pb.dirInfo.ioFDirIndex = 0;
3857 /* Check for errors */
3858 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3861 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3863 ret = HOpenResFile( app_vol , pb.dirInfo.ioDrDirID , "\psound.rsrc" , permission );
3867 for( i = 0 ; i < 7 ; i++ )
3868 soundmode[i] = false;
3870 for( i = 1 ; i < SOUND_MAX ; i++ ){
3871 /* Get the proper sound name */
3872 sprintf((char*)sound + 1, "%.16s.wav", angband_sound_name[i]);
3873 sound[0] = strlen((char*)sound + 1);
3875 /* Obtain resource XXX XXX XXX */
3876 handle = Get1NamedResource('snd ', sound);
3877 if( handle == NULL || ext_sound )
3878 handle = GetNamedResource('snd ', sound);
3881 soundmode[soundchoice[i]] = true;
3890 static void init_graf( void )
3894 SignedByte permission = fsRdPerm;
3900 /* Descend into "lib" folder */
3901 pb.dirInfo.ioCompletion = NULL;
3902 pb.dirInfo.ioNamePtr = "\plib";
3903 pb.dirInfo.ioVRefNum = app_vol;
3904 pb.dirInfo.ioDrDirID = app_dir;
3905 pb.dirInfo.ioFDirIndex = 0;
3907 /* Check for errors */
3908 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3911 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3913 /* Descend into "lib/xtra" folder */
3914 pb.dirInfo.ioCompletion = NULL;
3915 pb.dirInfo.ioNamePtr = "\pxtra";
3916 pb.dirInfo.ioVRefNum = app_vol;
3917 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3918 pb.dirInfo.ioFDirIndex = 0;
3920 /* Check for errors */
3921 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3924 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3926 /* Descend into "lib/xtra/graf" folder */
3927 pb.dirInfo.ioCompletion = NULL;
3928 pb.dirInfo.ioNamePtr = "\pgraf";
3929 pb.dirInfo.ioVRefNum = app_vol;
3930 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3931 pb.dirInfo.ioFDirIndex = 0;
3933 /* Check for errors */
3934 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3937 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3939 ret = HOpenResFile( app_vol , pb.dirInfo.ioDrDirID , "\pgraf.rsrc" , permission );
3944 /* Obtain resource XXX XXX XXX */
3945 handle = Get1NamedResource('PICT', graf);
3946 if ( handle == NULL || ext_graf )
3947 handle = GetNamedResource('PICT', "\pgraf.rsrc");
3954 #endif /* MACH_O_CARBON */
3960 static void init_chuukei( void )
3966 path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "chuukei.txt");
3968 fp = fopen(path, "r");
3973 if (fgets(tmp, 1024, fp)){
3975 int n = strlen(tmp);
3981 chuukei_server = TRUE;
3982 if(connect_chuukei_server(&tmp[2])<0){
3983 msg_print("connect fail");
3986 msg_print("connect");
3993 chuukei_client = TRUE;
3994 connect_chuukei_server(&tmp[2]);
4010 short InevrtCheck( DialogPtr targetDlg, short check )
4017 GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
4018 result = (GetControlValue( (ControlHandle)checkH ) + 1 ) % 2;
4019 SetControlValue( (ControlHandle)checkH , result );
4027 short SetCheck( DialogPtr targetDlg, short check, long result )
4034 GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
4035 SetControlValue( (ControlHandle)checkH , result );
4043 short GetCheck( DialogPtr targetDlg, short check )
4050 GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
4051 result = GetControlValue( (ControlHandle)checkH );
4055 void SoundConfigDLog(void)
4061 dialog=GetNewDialog(131, 0, (WindowPtr)-1);
4062 SetDialogDefaultItem( dialog, ok );
4063 SetDialogCancelItem( dialog, cancel );
4064 for( i = 1 ; i < 7 ; i++ )
4065 SetCheck( dialog, i+2 , soundmode[i] );
4067 /* ShowWindow(dialog); */
4068 for( item_hit = 100 ; cancel < item_hit ; ){
4069 ModalDialog(0, &item_hit);
4073 for( i = 1 ; i < 7 ; i++ )
4074 soundmode[i] = GetCheck( dialog, i+2 );
4079 InevrtCheck( dialog, item_hit );
4082 DisposeDialog(dialog);
4090 #if TARGET_API_MAC_CARBON
4091 static void save_pref_file(void)
4096 static void save_pref_file(void)
4105 /* Assume failure */
4108 /* Assume failure */
4125 /* Find the folder */
4126 err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
4132 /* Extract a path name */
4133 PathNameFromDirID(dirID, vref, (StringPtr)foo);
4135 /* Convert the string */
4136 ptocstr((StringPtr)foo);
4138 /* Append the preference file name */
4139 strcat(foo, PREF_FILE_NAME);
4141 /* Open the preference file */
4142 /* my_fopen set file type and file creator for MPW */
4143 fff = my_fopen(foo, "w");
4150 #endif /* USE_SFL_CODE */
4156 HGetVol(0, &savev, &saved);
4158 /* Go to "system" folder */
4159 SysEnvirons(curSysEnvVers, &env);
4160 SetVol(0, env.sysVRefNum);
4162 /* Open the preference file */
4163 /* my_fopen set file type and file creator for MPW */
4164 fff = fopen(PREF_FILE_NAME, "w");
4167 HSetVol(0, savev, saved);
4170 /* Save preferences */
4173 /* Write the preferences */
4184 #if defined(__MWERKS__)
4187 * A simple "Yes/No" filter to parse "key press" events in dialog windows
4189 static pascal Boolean ynfilter(DialogPtr dialog, EventRecord *event, short *ip)
4191 /* Parse key press events */
4192 if (event->what == keyDown)
4197 /* Extract the pressed key */
4198 c = (event->message & charCodeMask);
4200 /* Accept "no" and <return> and <enter> */
4201 if ((c=='n') || (c=='N') || (c==13) || (c==3)) i = 1;
4204 else if ((c=='y') || (c=='Y')) i = 2;
4206 /* Handle "yes" or "no" */
4210 ControlHandle control;
4213 /* Get the button */
4214 GetDialogItem(dialog, i, &type, (Handle*)&control, &r);
4216 /* Blink button for 1/10 second */
4217 HiliteControl(control, 1);
4218 Term_xtra_mac(TERM_XTRA_DELAY, 100);
4219 HiliteControl(control, 0);
4231 #endif /* __MWERKS__ */
4234 #if TARGET_API_MAC_CARBON
4237 * Prepare savefile dialogue and set the variable
4238 * savefile accordingly. Returns true if it succeeds, false (or
4239 * aborts) otherwise. If all is false, only allow files whose type
4241 * Originally written by Peter Ammon
4243 static bool select_savefile(bool all)
4246 FSSpec theFolderSpec;
4247 FSSpec savedGameSpec;
4248 NavDialogOptions dialogOptions;
4249 NavReplyRecord reply;
4250 /* Used only when 'all' is true */
4251 NavTypeList types = {ANGBAND_CREATOR, 1, 1, {'SAVE'}};
4252 NavTypeListHandle myTypeList;
4253 AEDesc defaultLocation;
4255 #ifdef MACH_O_CARBON
4257 /* Find the save folder */
4258 err = path_to_spec(ANGBAND_DIR_SAVE, &theFolderSpec);
4262 /* Find :lib:save: folder */
4263 err = FSMakeFSSpec(app_vol, app_dir, "\p:lib:save:", &theFolderSpec);
4268 if (err != noErr) quit("Unable to find the folder :lib:save:");
4270 /* Get default Navigator dialog options */
4271 err = NavGetDefaultDialogOptions(&dialogOptions);
4273 /* Clear preview option */
4274 dialogOptions.dialogOptionFlags &= ~kNavAllowPreviews;
4276 /* Disable multiple file selection */
4277 dialogOptions.dialogOptionFlags &= ~kNavAllowMultipleFiles;
4279 /* Make descriptor for default location */
4280 err = AECreateDesc(typeFSS, &theFolderSpec, sizeof(FSSpec),
4284 if (err != noErr) quit("Unable to allocate descriptor");
4286 /* We are indifferent to signature and file types */
4289 myTypeList = (NavTypeListHandle)nil;
4292 /* Set up type handle */
4295 err = PtrToHand(&types, (Handle *)&myTypeList, sizeof(NavTypeList));
4298 if (err != noErr) quit("Error in PtrToHand. Try enlarging heap");
4302 /* Call NavGetFile() with the types list */
4303 err = NavChooseFile(&defaultLocation, &reply, &dialogOptions, NULL,
4304 NULL, NULL, myTypeList, NULL);
4306 /* Free type list */
4307 if (!all) DisposeHandle((Handle)myTypeList);
4315 /* Invalid response -- allow the user to cancel */
4316 else if (!reply.validRecord)
4318 /* Hack -- Fake error */
4322 /* Retrieve FSSpec from the reply */
4325 AEKeyword theKeyword;
4326 DescType actualType;
4329 /* Get a pointer to selected file */
4330 (void)AEGetNthPtr(&reply.selection, 1, typeFSS, &theKeyword,
4331 &actualType, &savedGameSpec, sizeof(FSSpec), &actualSize);
4333 /* Dispose NavReplyRecord, resources and descriptors */
4334 (void)NavDisposeReply(&reply);
4337 /* Dispose location info */
4338 AEDisposeDesc(&defaultLocation);
4341 if (err != noErr) return (FALSE);
4343 #ifdef MACH_O_CARBON
4345 /* Convert FSSpec to pathname and store it in variable savefile */
4346 (void)spec_to_path(&savedGameSpec, savefile, sizeof(savefile));
4350 /* Convert FSSpec to pathname and store it in variable savefile */
4353 savedGameSpec.parID,
4354 savedGameSpec.vRefNum,
4355 (char *)savedGameSpec.name);
4366 * Handle menu: "File" + "New"
4368 static void do_menu_file_new(void)
4373 /* Game is in progress */
4374 game_in_progress = 1;
4388 * Handle menu: "File" + "Open"
4390 #if TARGET_API_MAC_CARBON
4391 static void do_menu_file_open(bool all)
4393 /* Let the player to choose savefile */
4394 if (!select_savefile(all)) return;
4399 /* Game is in progress */
4400 game_in_progress = TRUE;
4412 static void do_menu_file_open(bool all)
4426 /* vrefnum = GetSFCurVol(); */
4427 vrefnum = -*((short*)0x214);
4429 /* drefnum = GetSFCurDir(); */
4430 drefnum = *((long*)0x398);
4432 /* Descend into "lib" folder */
4433 pb.ioCompletion = NULL;
4434 pb.ioNamePtr = "\plib";
4435 pb.ioVRefNum = vrefnum;
4436 pb.ioDrDirID = drefnum;
4439 /* Check for errors */
4440 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
4443 if ((err == noErr) && (pb.ioFlAttrib & 0x10))
4445 /* Descend into "lib/save" folder */
4446 pb.ioCompletion = NULL;
4447 pb.ioNamePtr = "\psave";
4448 pb.ioVRefNum = vrefnum;
4449 pb.ioDrDirID = pb.ioDrDirID;
4452 /* Check for errors */
4453 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
4456 if ((err == noErr) && (pb.ioFlAttrib & 0x10))
4458 /* SetSFCurDir(pb.ioDrDirID); */
4459 *((long*)0x398) = pb.ioDrDirID;
4463 /* Window location */
4464 topleft.h = (qd.screenBits.bounds.left+qd.screenBits.bounds.right)/2-344/2;
4465 topleft.v = (2*qd.screenBits.bounds.top+qd.screenBits.bounds.bottom)/3-188/2;
4467 /* Allow "all" files */
4471 SFGetFile(topleft, "\p", NULL, -1, types, NULL, &reply);
4474 /* Allow "save" files */
4481 SFGetFile(topleft, "\p", NULL, 1, types, NULL, &reply);
4485 if (!reply.good) return;
4487 /* Extract textual file name for save file */
4488 GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
4489 refnum_to_name(savefile, drefnum, vrefnum, (char*)reply.fName);
4494 /* Game is in progress */
4495 game_in_progress = 1;
4510 * Handle the "open_when_ready" flag
4512 static void handle_open_when_ready(void)
4514 /* Check the flag XXX XXX XXX make a function for this */
4515 if (open_when_ready && initialized && !game_in_progress)
4518 open_when_ready = FALSE;
4520 /* Game is in progress */
4521 game_in_progress = 1;
4540 * Initialize the menus
4542 * Apple (128) = { About, -, ... }
4543 * File (129) = { New,Open,Import,Close,Save,-,Exit,Quit }
4544 * Edit (130) = { Cut, Copy, Paste, Clear } (?)
4545 * Font (131) = { Bold, Extend, -, Monaco, ..., -, ... }
4546 * Size (132) = { ... }
4547 * Window (133) = { Angband, Mirror, Recall, Choice,
4548 * Term-4, Term-5, Term-6, Term-7 }
4549 * Special (134) = { Sound, Graphics, TileWidth, TileHeight, -,
4554 #define MENU_APPLE 128
4555 #define ITEM_ABOUT 1
4558 #define MENU_FILE 129
4560 # define ITEM_OPEN 2
4561 # define ITEM_IMPORT 3
4562 # define ITEM_CLOSE 4
4563 # define ITEM_SAVE 5
4564 # define ITEM_QUIT 7
4567 #define MENU_EDIT 130
4568 # define ITEM_UNDO 1
4570 # define ITEM_COPY 4
4571 # define ITEM_PASTE 5
4572 # define ITEM_CLEAR 6
4575 #define MENU_FONT 131
4576 # define ITEM_BOLD 1
4577 # define ITEM_WIDE 2
4580 #define MENU_SIZE 132
4583 #define MENU_WINDOWS 133
4586 #define MENU_SPECIAL 134
4587 # define ITEM_SOUND 1
4588 # define ITEM_GRAPH 2
4589 # define ITEM_TILEWIDTH 3
4590 # define ITEM_TILEHEIGHT 4
4591 # define ITEM_FIDDLE 6
4592 # define ITEM_WIZARD 7
4594 /* Sounds submenu */
4595 #define SUBMENU_SOUND 143
4596 # define ITEM_USE_SOUND 1
4597 # define ITEM_SOUND_SETTING 2
4599 /* Graphics submenu */
4600 #define SUBMENU_GRAPH 144
4601 # define ITEM_NONE 1
4603 # define ITEM_16X16 3
4604 # define ITEM_BIGTILE 5
4606 /* TileWidth submenu */
4607 #define SUBMENU_TILEWIDTH 145
4609 /* TileHeight submenu */
4610 #define SUBMENU_TILEHEIGHT 146
4613 static void init_menubar(void)
4625 #if TARGET_API_MAC_CARBON
4630 /* Get the "apple" menu */
4631 mbar = GetNewMBar(128);
4634 if (mbar == nil) quit(_("メニューバー ID 128を見つける事ができません!", "Cannot find menubar('MBAR') id 128!"));
4636 /* Insert them into the current menu list */
4640 DisposeHandle(mbar);
4642 #if !TARGET_API_MAC_CARBON
4643 /* Apple menu (id 128) */
4644 m = GetMenuHandle(MENU_APPLE);
4646 /* Add the DA's to the "apple" menu */
4647 AppendResMenu (m, 'DRVR');
4650 /* Get the "File" menu */
4651 #if TARGET_API_MAC_CARBON
4652 m = GetMenuHandle(MENU_FILE);
4653 err = Gestalt( gestaltSystemVersion, &response );
4654 if ( (err == noErr) && (response >= 0x00000A00) )
4656 DeleteMenuItem(m, ITEM_QUIT);
4660 /* Edit menu (id 130) - we don't have to do anything */
4663 * Font menu (id 131) - append names of mono-spaced fonts
4664 * followed by all available ones
4666 m = GetMenuHandle(MENU_FONT);
4669 r.left = r.right = r.top = r.bottom = 0;
4671 /* Make the fake window */
4672 tmpw = NewWindow(0, &r, "\p", false, documentProc, 0, 0, 0);
4674 /* Activate the "fake" window */
4675 #if TARGET_API_MAC_CARBON
4676 SetPortWindowPort(tmpw);
4687 /* Add the fonts to the menu */
4688 AppendResMenu(m, 'FONT');
4691 #if TARGET_API_MAC_CARBON
4692 n = CountMenuItems(m);
4698 for (i = n; i >= 4; i--)
4703 /* Acquire the font name */
4704 GetMenuItemText(m, i, tmpName);
4706 /* Acquire the font index */
4707 #if TARGET_API_MAC_CARBON
4708 fontNum = FMGetFontFamilyFromName( tmpName );
4710 GetFNum(tmpName, &fontNum);
4713 /* Apply the font index */
4716 /* Remove non-mono-spaced fonts */
4717 if ((CharWidth('i') != CharWidth('W')) || (CharWidth('W') == 0))
4719 /* Delete the menu item XXX XXX XXX */
4720 DeleteMenuItem (m, i);
4724 /* Destroy the old window */
4725 DisposeWindow(tmpw);
4727 /* Add a separator */
4728 AppendMenu(m, "\p-");
4730 /* Add the fonts to the menu */
4731 AppendResMenu (m, 'FONT');
4734 /* Size menu (id 132) */
4735 m = GetMenuHandle(MENU_SIZE);
4737 /* Add some sizes (stagger choices) */
4738 for (i = 8; i <= 32; i += ((i / 16) + 1))
4743 sprintf((char*)buf + 1, "%d", i);
4744 buf[0] = strlen((char*)buf + 1);
4751 /* Windows menu (id 133) */
4752 m = GetMenuHandle(MENU_WINDOWS);
4754 /* Default choices */
4755 for (i = 0; i < MAX_TERM_DATA; i++)
4759 /* Describe the item */
4760 sprintf((char*)buf + 1, "%.15s", angband_term_name[i]);
4761 buf[0] = strlen((char*)buf + 1);
4766 /* Command-Key shortcuts */
4767 if (i < 8) SetItemCmd(m, i + 1, '0' + i);
4771 #if TARGET_API_MAC_CARBON && !defined(MAC_MPW)
4773 /* CW or gcc -- Use recommended interface for hierarchical menus */
4775 /* Special menu (id 134) */
4776 m = GetMenuHandle(MENU_SPECIAL);
4778 /* Insert Graphics submenu (id 143) */
4782 /* Get the submenu */
4783 submenu = GetMenu(SUBMENU_SOUND);
4786 SetMenuItemHierarchicalMenu(m, ITEM_SOUND, submenu);
4789 /* Insert Graphics submenu (id 144) */
4793 /* Get the submenu */
4794 submenu = GetMenu(SUBMENU_GRAPH);
4797 SetMenuItemHierarchicalMenu(m, ITEM_GRAPH, submenu);
4800 /* Insert TileWidth submenu (id 145) */
4804 /* Get the submenu */
4805 submenu = GetMenu(SUBMENU_TILEWIDTH);
4807 /* Add some sizes */
4808 for (i = 4, n = 1; i <= 32; i++, n++)
4813 strnfmt((char*)buf + 1, 15, "%d", i);
4814 buf[0] = strlen((char*)buf + 1);
4817 AppendMenu(submenu, buf);
4821 SetMenuItemHierarchicalMenu(m, ITEM_TILEWIDTH, submenu);
4824 /* Insert TileHeight submenu (id 146) */
4828 /* Get the submenu */
4829 submenu = GetMenu(SUBMENU_TILEHEIGHT);
4832 /* Add some sizes */
4833 for (i = 4, n = 1; i <= 32; i++, n++)
4838 strnfmt((char*)buf + 1, 15, "%d", i);
4839 buf[0] = strlen((char*)buf + 1);
4842 AppendMenu(submenu, buf);
4846 SetMenuItemHierarchicalMenu(m, ITEM_TILEHEIGHT, submenu);
4851 /* Special menu (id 134) */
4853 /* Get graphics (sub)menu (id 143) */
4854 m = GetMenu(SUBMENU_SOUND);
4856 /* Insert it as a submenu */
4857 InsertMenu(m, hierMenu);
4860 /* Get graphics (sub)menu (id 144) */
4861 m = GetMenu(SUBMENU_GRAPH);
4863 /* Insert it as a submenu */
4864 InsertMenu(m, hierMenu);
4867 /* Get TileWidth (sub)menu (id 145) */
4868 m = GetMenu(SUBMENU_TILEWIDTH);
4870 /* Add some sizes */
4871 for (i = 4; i <= 32; i++)
4876 sprintf((char*)buf + 1, "%d", i);
4877 buf[0] = strlen((char*)buf + 1);
4884 /* Insert it as a submenu */
4885 InsertMenu(m, hierMenu);
4887 /* Get TileHeight (sub)menu (id 146) */
4888 m = GetMenu(SUBMENU_TILEHEIGHT);
4890 /* Add some sizes */
4891 for (i = 4; i <= 32; i++)
4896 sprintf((char*)buf + 1, "%d", i);
4897 buf[0] = strlen((char*)buf + 1);
4904 /* Insert the menu */
4905 InsertMenu(m, hierMenu);
4908 /* Update the menu bar */
4916 static void setup_menus(void)
4926 term_data *td = NULL;
4929 /* Relevant "term_data" */
4930 for (i = 0; i < MAX_TERM_DATA; i++)
4933 if (!data[i].t) continue;
4935 /* Notice the matching window */
4936 if (data[i].w == FrontWindow()) td = &data[i];
4941 m = GetMenuHandle(MENU_FILE);
4944 #if TARGET_API_MAC_CARBON
4945 n = CountMenuItems(m);
4951 for (i = 1; i <= n; i++)
4954 #if TARGET_API_MAC_CARBON
4955 DisableMenuItem(m, i);
4956 CheckMenuItem(m, i, FALSE);
4959 CheckItem(m, i, FALSE);
4963 /* Enable "new"/"open..."/"import..." */
4964 if (initialized && !game_in_progress)
4966 #if TARGET_API_MAC_CARBON
4967 EnableMenuItem(m, ITEM_NEW);
4968 EnableMenuItem(m, ITEM_OPEN);
4969 EnableMenuItem(m, ITEM_IMPORT);
4971 EnableItem(m, ITEM_NEW);
4972 EnableItem(m, ITEM_OPEN);
4973 EnableItem(m, ITEM_IMPORT);
4977 /* Enable "close" */
4980 #if TARGET_API_MAC_CARBON
4981 EnableMenuItem(m, ITEM_CLOSE);
4983 EnableItem(m, ITEM_CLOSE);
4988 if (initialized && character_generated)
4990 #if TARGET_API_MAC_CARBON
4991 EnableMenuItem(m, ITEM_SAVE);
4993 EnableItem(m, ITEM_SAVE);
5000 #if TARGET_API_MAC_CARBON
5001 EnableMenuItem(m, ITEM_QUIT);
5003 EnableItem(m, ITEM_QUIT);
5009 m = GetMenuHandle(MENU_EDIT);
5012 #if TARGET_API_MAC_CARBON
5013 n = CountMenuItems(m);
5019 for (i = 1; i <= n; i++)
5022 #if TARGET_API_MAC_CARBON
5023 DisableMenuItem(m, i);
5024 CheckMenuItem(m, i, FALSE);
5027 CheckItem(m, i, FALSE);
5031 /* Enable "edit" options if "needed" */
5034 #if TARGET_API_MAC_CARBON
5035 EnableMenuItem(m, ITEM_UNDO);
5036 EnableMenuItem(m, ITEM_CUT);
5037 EnableMenuItem(m, ITEM_COPY);
5038 EnableMenuItem(m, ITEM_PASTE);
5039 EnableMenuItem(m, ITEM_CLEAR);
5041 EnableItem(m, ITEM_UNDO);
5042 EnableItem(m, ITEM_CUT);
5043 EnableItem(m, ITEM_COPY);
5044 EnableItem(m, ITEM_PASTE);
5045 EnableItem(m, ITEM_CLEAR);
5051 m = GetMenuHandle(MENU_FONT);
5054 #if TARGET_API_MAC_CARBON
5055 n = CountMenuItems(m);
5061 for (i = 1; i <= n; i++)
5064 #if TARGET_API_MAC_CARBON
5065 DisableMenuItem(m, i);
5066 CheckMenuItem(m, i, FALSE);
5069 CheckItem(m, i, FALSE);
5073 /* Hack -- look cute XXX XXX */
5074 /* SetItemStyle(m, 1, bold); */
5076 /* Hack -- look cute XXX XXX */
5077 /* SetItemStyle(m, 2, extend); */
5082 #if TARGET_API_MAC_CARBON
5084 EnableMenuItem(m, ITEM_BOLD);
5086 /* Enable "extend" */
5087 EnableMenuItem(m, ITEM_WIDE);
5089 /* Check the appropriate "bold-ness" */
5090 if (td->font_face & bold) CheckMenuItem(m, ITEM_BOLD, TRUE);
5092 /* Check the appropriate "wide-ness" */
5093 if (td->font_face & extend) CheckMenuItem(m, ITEM_WIDE, TRUE);
5096 for (i = 4; i <= n; i++)
5099 EnableMenuItem(m, i);
5102 GetMenuItemText(m, i, s);
5105 /* Check active font */
5106 if (td->font_id == value) CheckMenuItem(m, i, TRUE);
5110 EnableItem(m, ITEM_BOLD);
5112 /* Enable "extend" */
5113 EnableItem(m, ITEM_WIDE);
5115 /* Check the appropriate "bold-ness" */
5116 if (td->font_face & bold) CheckItem(m, ITEM_BOLD, TRUE);
5118 /* Check the appropriate "wide-ness" */
5119 if (td->font_face & extend) CheckItem(m, ITEM_WIDE, TRUE);
5122 for (i = 4; i <= n; i++)
5128 GetMenuItemText(m, i, s);
5131 /* Check active font */
5132 if (td->font_id == value) CheckItem(m, i, TRUE);
5139 m = GetMenuHandle(MENU_SIZE);
5142 #if TARGET_API_MAC_CARBON
5143 n = CountMenuItems(m);
5149 for (i = 1; i <= n; i++)
5152 #if TARGET_API_MAC_CARBON
5153 DisableMenuItem(m, i);
5154 CheckMenuItem(m, i, FALSE);
5157 CheckItem(m, i, FALSE);
5165 for (i = 1; i <= n; i++)
5168 GetMenuItemText(m, i, s);
5170 value = atoi((char*)(s+1));
5172 #if TARGET_API_MAC_CARBON
5173 /* Enable the "real" sizes */
5174 if (RealFont(td->font_id, value)) EnableMenuItem(m, i);
5176 /* Check the current size */
5177 if (td->font_size == value) CheckMenuItem(m, i, TRUE);
5179 /* Enable the "real" sizes */
5180 if (RealFont(td->font_id, value)) EnableItem(m, i);
5182 /* Check the current size */
5183 if (td->font_size == value) CheckItem(m, i, TRUE);
5190 m = GetMenuHandle(MENU_WINDOWS);
5193 #if TARGET_API_MAC_CARBON
5194 n = CountMenuItems(m);
5199 /* Check active windows */
5200 for (i = 1; i <= n; i++)
5202 /* Check if needed */
5203 #if TARGET_API_MAC_CARBON
5204 CheckMenuItem(m, i, data[i-1].mapped);
5206 CheckItem(m, i, data[i-1].mapped);
5212 m = GetMenuHandle(MENU_SPECIAL);
5215 #if TARGET_API_MAC_CARBON
5216 n = CountMenuItems(m);
5222 for (i = 1; i <= n; i++)
5225 #if TARGET_API_MAC_CARBON
5226 DisableMenuItem(m, i);
5229 /* XXX Oh no, this removes submenu... */
5230 if ((i != ITEM_SOUND) &&
5231 (i != ITEM_GRAPH) &&
5232 (i != ITEM_TILEWIDTH) &&
5233 (i != ITEM_TILEHEIGHT)) CheckMenuItem(m, i, FALSE);
5236 CheckMenuItem(m, i, FALSE);
5242 /* XXX Oh no, this removes submenu... */
5243 if ((i != ITEM_SOUND) &&
5244 (i != ITEM_GRAPH) &&
5245 (i != ITEM_TILEWIDTH) &&
5246 (i != ITEM_TILEHEIGHT)) CheckItem(m, i, FALSE);
5250 #if TARGET_API_MAC_CARBON
5251 /* Item "arg_sound" */
5252 EnableMenuItem(m, ITEM_SOUND);
5258 /* MPW's Universal Interface is a bit out of date */
5260 /* Graphics submenu */
5261 submenu = GetMenuHandle(SUBMENU_SOUND);
5265 /* Graphics submenu */
5266 (void)GetMenuItemHierarchicalMenu(m, ITEM_SOUND, &submenu);
5271 n = CountMenuItems(submenu);
5274 for (i = 1; i <= n; i++)
5277 DisableMenuItem(submenu, i);
5278 CheckMenuItem(submenu, i, FALSE);
5281 /* Item "Sound On/Off" */
5282 EnableMenuItem(submenu, ITEM_USE_SOUND);
5283 CheckMenuItem(submenu, ITEM_USE_SOUND, arg_sound);
5285 /* Item "Sounf Config" */
5286 #ifndef MACH_O_CARBON
5287 EnableMenuItem(submenu, ITEM_SOUND_SETTING);
5291 /* Item "Graphics" */
5292 EnableMenuItem(m, ITEM_GRAPH);
5298 /* MPW's Universal Interface is a bit out of date */
5300 /* Graphics submenu */
5301 submenu = GetMenuHandle(SUBMENU_GRAPH);
5305 /* Graphics submenu */
5306 (void)GetMenuItemHierarchicalMenu(m, ITEM_GRAPH, &submenu);
5311 n = CountMenuItems(submenu);
5314 for (i = 1; i <= n; i++)
5317 DisableMenuItem(submenu, i);
5318 CheckMenuItem(submenu, i, FALSE);
5322 EnableMenuItem(submenu, ITEM_NONE);
5323 CheckMenuItem(submenu, ITEM_NONE, (graf_mode == GRAF_MODE_NONE));
5326 EnableMenuItem(submenu, ITEM_8X8);
5327 CheckMenuItem(submenu, ITEM_8X8, (graf_mode == GRAF_MODE_8X8));
5330 EnableMenuItem(submenu, ITEM_16X16);
5331 CheckMenuItem(submenu, ITEM_16X16, (graf_mode == GRAF_MODE_16X16));
5333 /* Item "Big tiles" */
5334 EnableMenuItem(submenu, ITEM_BIGTILE);
5335 CheckMenuItem(submenu, ITEM_BIGTILE, arg_bigtile);
5338 /* Item "TileWidth" */
5339 EnableMenuItem(m, ITEM_TILEWIDTH);
5345 /* MPW's Universal Interface is a bit out of date */
5347 /* TIleWidth submenu */
5348 submenu = GetMenuHandle(SUBMENU_TILEWIDTH);
5352 /* TileWidth submenu */
5353 (void)GetMenuItemHierarchicalMenu(m, ITEM_TILEWIDTH, &submenu);
5358 n = CountMenuItems(submenu);
5361 for (i = 1; i <= n; i++)
5364 DisableMenuItem(submenu, i);
5365 CheckMenuItem(submenu, i, FALSE);
5372 for (i = 1; i <= n; i++)
5375 /* GetMenuItemText(m,i,s); */
5376 GetMenuItemText(submenu, i, s);
5378 value = atoi((char*)(s+1));
5381 if (value >= td->font_wid) EnableMenuItem(submenu, i);
5383 /* Check the current size */
5384 if (td->tile_wid == value) CheckMenuItem(submenu, i, TRUE);
5389 /* Item "TileHeight" */
5390 EnableMenuItem(m, ITEM_TILEHEIGHT);
5396 /* MPW's Universal Interface is a bit out of date */
5398 /* TileHeight submenu */
5399 submenu = GetMenuHandle(SUBMENU_TILEHEIGHT);
5403 /* TileWidth submenu */
5404 (void)GetMenuItemHierarchicalMenu(m, ITEM_TILEHEIGHT, &submenu);
5409 n = CountMenuItems(submenu);
5412 for (i = 1; i <= n; i++)
5415 DisableMenuItem(submenu, i);
5416 CheckMenuItem(submenu, i, FALSE);
5423 for (i = 1; i <= n; i++)
5426 /* GetMenuItemText(m,i,s); */
5427 GetMenuItemText(submenu, i, s);
5429 value = atoi((char*)(s+1));
5432 if (value >= td->font_hgt) EnableMenuItem(submenu, i);
5434 /* Check the current size */
5435 if (td->tile_hgt == value) CheckMenuItem(submenu, i, TRUE);
5440 /* Item "arg_fiddle" */
5441 EnableMenuItem(m, ITEM_FIDDLE);
5442 CheckMenuItem(m, ITEM_FIDDLE, arg_fiddle);
5444 /* Item "arg_wizard" */
5445 EnableMenuItem(m, ITEM_WIZARD);
5446 CheckMenuItem(m, ITEM_WIZARD, arg_wizard);
5449 /* Item "arg_sound" */
5450 EnableItem(m, ITEM_SOUND);
5452 /* Item "arg_graphics" */
5453 EnableItem(m, ITEM_GRAPH);
5455 /* Item "TileWidth" */
5456 EnableItem(m, ITEM_TILEWIDTH);
5458 /* Item "TileHeight" */
5459 EnableItem(m, ITEM_TILEHEIGHT);
5461 /* Item "arg_fiddle" */
5462 EnableItem(m, ITEM_FIDDLE);
5463 CheckItem(m, ITEM_FIDDLE, arg_fiddle);
5465 /* Item "arg_wizard" */
5466 EnableItem(m, ITEM_WIZARD);
5467 CheckItem(m, ITEM_WIZARD, arg_wizard);
5469 /* Sounds submenu */
5470 m = GetMenuHandle(SUBMENU_SOUND);
5476 for (i = 1; i <= n; i++)
5480 CheckItem(m, i, FALSE);
5483 /* Item "Sound On/Off" */
5484 EnableItem(m, ITEM_USE_SOUND);
5485 CheckItem(m, ITEM_USE_SOUND, arg_sound);
5487 /* Item "Sound Config" */
5488 EnableItem(m, ITEM_SOUND_SETTING);
5490 /* Graphics submenu */
5491 m = GetMenuHandle(SUBMENU_GRAPH);
5497 for (i = 1; i <= n; i++)
5501 CheckItem(m, i, FALSE);
5505 EnableItem(m, ITEM_NONE);
5506 CheckItem(m, ITEM_NONE, (graf_mode == GRAF_MODE_NONE));
5509 EnableItem(m, ITEM_8X8);
5510 CheckItem(m, ITEM_8X8, (graf_mode == GRAF_MODE_8X8));
5513 EnableItem(m, ITEM_16X16);
5514 CheckItem(m, ITEM_16X16, (graf_mode == GRAF_MODE_16X16));
5516 /* Item "Bigtile" */
5517 EnableItem(m, ITEM_BIGTILE);
5518 CheckItem(m, ITEM_BIGTILE, arg_bigtile);
5521 /* TIleWidth submenu */
5522 m = GetMenuHandle(SUBMENU_TILEWIDTH);
5528 for (i = 1; i <= n; i++)
5532 CheckItem(m, i, FALSE);
5539 for (i = 1; i <= n; i++)
5542 /* GetMenuItemText(m,i,s); */
5543 GetMenuItemText(m, i, s);
5545 value = atoi((char*)(s+1));
5548 if (value >= td->font_wid) EnableItem(m, i);
5550 /* Check the current size */
5551 if (td->tile_wid == value) CheckItem(m, i, TRUE);
5556 /* TileHeight submenu */
5557 m = GetMenuHandle(SUBMENU_TILEHEIGHT);
5563 for (i = 1; i <= n; i++)
5567 CheckItem(m, i, FALSE);
5574 for (i = 1; i <= n; i++)
5577 GetMenuItemText(m, i, s);
5579 value = atoi((char*)(s+1));
5582 if (value >= td->font_hgt) EnableItem(m, i);
5584 /* Check the current size */
5585 if (td->tile_hgt == value) CheckItem(m, i, TRUE);
5594 * Process a menu selection (see above)
5596 * Hack -- assume that invalid menu selections are disabled above,
5597 * which I have been informed may not be reliable. XXX XXX XXX
5599 static void menu(long mc)
5603 int menuid, selection;
5605 static unsigned char s[1000];
5609 term_data *td = NULL;
5614 /* Analyze the menu command */
5615 menuid = HiWord(mc);
5616 selection = LoWord(mc);
5619 /* Find the window */
5620 for (i = 0; i < MAX_TERM_DATA; i++)
5622 /* Skip dead windows */
5623 if (!data[i].t) continue;
5625 /* Notice matches */
5626 if (data[i].w == FrontWindow()) td = &data[i];
5630 /* Branch on the menu */
5636 /* About Angband... */
5637 #if TARGET_API_MAC_CARBON
5638 if (selection == ITEM_ABOUT)
5643 /* Get the about dialogue */
5644 dialog=GetNewDialog(128, 0, (WindowPtr)-1);
5646 /* Move it to the middle of the screen */
5648 GetDialogWindow(dialog),
5650 kWindowCenterOnMainScreen);
5652 /* Show the dialog */
5653 TransitionWindow(GetDialogWindow(dialog),
5654 kWindowZoomTransitionEffect,
5655 kWindowShowTransitionAction,
5658 /* Wait for user to click on it */
5659 ModalDialog(0, &item_hit);
5661 /* Free the dialogue */
5662 DisposeDialog(dialog);
5666 if (selection == ITEM_ABOUT)
5672 dialog=GetNewDialog(128, 0, (WindowPtr)-1);
5675 center_rect(&r, &qd.screenBits.bounds);
5676 MoveWindow(dialog, r.left, r.top, 1);
5678 ModalDialog(0, &item_hit);
5679 DisposeDialog(dialog);
5683 /* Desk accessory */
5684 GetMenuItemText(GetMenuHandle(MENU_APPLE), selection, s);
5705 do_menu_file_open(FALSE);
5712 do_menu_file_open(TRUE);
5726 td->t->mapped_flag = FALSE;
5728 /* Hide the window */
5738 plog(_("今はセーブすることは出来ません。", "You may not do that right now."));
5742 /* Hack -- Forget messages */
5745 /* Hack -- Save the game */
5746 do_cmd_save_game(FALSE);
5751 /* Quit (with save) */
5754 /* Save the game (if necessary) */
5755 if (game_in_progress && character_generated)
5758 plog(_("今はセーブすることは出来ません。", "You may not do that right now."));
5761 /* Hack -- Forget messages */
5766 do_cmd_save_game(FALSE);
5768 Term_key_push(SPECIAL_KEY_QUIT);
5790 /* Require a window */
5799 /* Toggle the "bold" setting */
5800 if (selection == ITEM_BOLD)
5802 /* Toggle the setting */
5803 if (td->font_face & bold)
5805 td->font_face &= ~bold;
5809 td->font_face |= bold;
5812 /* Tile Width Hight Init */
5813 td->tile_wid = td->tile_hgt = 0;
5815 /* Apply and Verify */
5816 term_data_check_font(td);
5817 term_data_check_size(td);
5819 /* Resize and Redraw */
5820 term_data_resize(td);
5821 term_data_redraw(td);
5826 /* Toggle the "wide" setting */
5827 if (selection == ITEM_WIDE)
5829 /* Toggle the setting */
5830 if (td->font_face & extend)
5832 td->font_face &= ~extend;
5836 td->font_face |= extend;
5839 /* Tile Width Hight Init */
5840 td->tile_wid = td->tile_hgt = 0;
5842 /* Apply and Verify */
5843 term_data_check_font(td);
5844 term_data_check_size(td);
5846 /* Resize and Redraw */
5847 term_data_resize(td);
5848 term_data_redraw(td);
5853 /* Get a new font name */
5854 GetMenuItemText(GetMenuHandle(MENU_FONT), selection, s);
5857 /* Save the new font id */
5860 /* Current size is bad for new font */
5861 if (!RealFont(td->font_id, td->font_size))
5863 /* Find similar size */
5864 for (i = 1; i <= 32; i++)
5866 /* Adjust smaller */
5867 if (td->font_size - i >= 8)
5869 if (RealFont(td->font_id, td->font_size - i))
5877 if (td->font_size + i <= 128)
5879 if (RealFont(td->font_id, td->font_size + i))
5888 /* Tile Width Hight Init */
5889 td->tile_wid = td->tile_hgt = 0;
5891 /* Apply and Verify */
5892 term_data_check_font(td);
5893 term_data_check_size(td);
5895 /* Resize and Redraw */
5896 term_data_resize(td);
5897 term_data_redraw(td);
5899 /* Restore the window */
5916 GetMenuItemText(GetMenuHandle(MENU_SIZE), selection, s);
5918 td->font_size = atoi((char*)(s+1));
5920 /* Tile Width Hight Init */
5921 td->tile_wid = td->tile_hgt = 0;
5923 /* Apply and Verify */
5924 term_data_check_font(td);
5925 term_data_check_size(td);
5927 /* Resize and Redraw */
5928 term_data_resize(td);
5929 term_data_redraw(td);
5943 /* Check legality of choice */
5944 if ((i < 0) || (i >= MAX_TERM_DATA)) break;
5946 /* Obtain the window */
5956 td->t->mapped_flag = TRUE;
5958 /* Show the window */
5961 /* Bring to the front */
5962 SelectWindow(td->w);
5974 arg_fiddle = !arg_fiddle;
5980 arg_wizard = !arg_wizard;
5988 /* Sounds submenu */
5993 case ITEM_USE_SOUND:
5995 /* Toggle arg_sound */
5996 arg_sound = !arg_sound;
5998 /* React to changes */
5999 Term_xtra(TERM_XTRA_REACT, 0);
6004 case ITEM_SOUND_SETTING:
6015 /* Graphics submenu */
6022 graf_mode_req = GRAF_MODE_NONE;
6029 graf_mode_req = GRAF_MODE_8X8;
6036 graf_mode_req = GRAF_MODE_16X16;
6044 term_data *td = &data[0];
6046 /* Toggle "arg_bigtile" */
6047 arg_bigtile = !arg_bigtile;
6050 Term_activate(td->t);
6052 /* Resize the term */
6053 Term_resize(td->cols, td->rows);
6062 /* Hack -- Force redraw */
6063 Term_key_push(KTRL('R'));
6068 /* TileWidth submenu */
6069 case SUBMENU_TILEWIDTH:
6080 GetMenuItemText(GetMenuHandle(SUBMENU_TILEWIDTH), selection, s);
6082 td->tile_wid = atoi((char*)(s+1));
6084 /* Apply and Verify */
6085 term_data_check_size(td);
6087 /* Resize and Redraw */
6088 term_data_resize(td);
6089 term_data_redraw(td);
6097 /* TileHeight submenu */
6098 case SUBMENU_TILEHEIGHT:
6109 GetMenuItemText(GetMenuHandle(SUBMENU_TILEHEIGHT), selection, s);
6111 td->tile_hgt = atoi((char*)(s+1));
6113 /* Apply and Verify */
6114 term_data_check_size(td);
6116 /* Resize and Redraw */
6117 term_data_resize(td);
6118 term_data_redraw(td);
6128 /* Clean the menu */
6137 * Check for extra required parameters -- From "Maarten Hazewinkel"
6139 static OSErr CheckRequiredAEParams(const AppleEvent *theAppleEvent)
6142 DescType returnedType;
6145 aeError = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard,
6146 &returnedType, NULL, 0, &actualSize);
6148 if (aeError == errAEDescNotFound) return (noErr);
6150 if (aeError == noErr) return (errAEParamMissed);
6157 * Apple Event Handler -- Open Application
6159 static pascal OSErr AEH_Start(const AppleEvent *theAppleEvent,
6160 AppleEvent *reply, long handlerRefCon)
6162 #pragma unused(reply, handlerRefCon)
6164 return (CheckRequiredAEParams(theAppleEvent));
6169 * Apple Event Handler -- Quit Application
6171 static pascal OSErr AEH_Quit(const AppleEvent *theAppleEvent,
6172 AppleEvent *reply, long handlerRefCon)
6174 #pragma unused(reply, handlerRefCon)
6175 #if TARGET_API_MAC_CARBON
6176 #pragma unused(theAppleEvent)
6178 /* Save the game (if necessary) */
6179 if (game_in_progress && character_generated)
6182 plog(_("今はセーブすることは出来ません。", "You may not do that right now."));
6185 /* Hack -- Forget messages */
6190 do_cmd_save_game(FALSE);
6192 Term_key_push(SPECIAL_KEY_QUIT);
6200 quit_when_ready = TRUE;
6202 /* Check arguments */
6203 return (CheckRequiredAEParams(theAppleEvent));
6209 * Apple Event Handler -- Print Documents
6211 static pascal OSErr AEH_Print(const AppleEvent *theAppleEvent,
6212 AppleEvent *reply, long handlerRefCon)
6214 #pragma unused(theAppleEvent, reply, handlerRefCon)
6216 return (errAEEventNotHandled);
6221 * Apple Event Handler by Steve Linberg (slinberg@crocker.com).
6223 * The old method of opening savefiles from the finder does not work
6224 * on the Power Macintosh, because CountAppFiles and GetAppFiles,
6225 * used to return information about the selected document files when
6226 * an application is launched, are part of the Segment Loader, which
6227 * is not present in the RISC OS due to the new memory architecture.
6229 * The "correct" way to do this is with AppleEvents. The following
6230 * code is modeled on the "Getting Files Selected from the Finder"
6231 * snippet from Think Reference 2.0. (The prior sentence could read
6232 * "shamelessly swiped & hacked")
6234 static pascal OSErr AEH_Open(const AppleEvent *theAppleEvent,
6235 AppleEvent* reply, long handlerRefCon)
6237 #pragma unused(reply, handlerRefCon)
6244 DescType returnedType;
6248 /* Put the direct parameter (a descriptor list) into a docList */
6249 err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &docList);
6250 if (err) return err;
6253 * We ignore the validity check, because we trust the FInder, and we only
6254 * allow one savefile to be opened, so we ignore the depth of the list.
6257 err = AEGetNthPtr(&docList, 1L, typeFSS, &keywd,
6258 &returnedType, (Ptr) &myFSS, sizeof(myFSS), &actualSize);
6259 if (err) return err;
6261 /* Only needed to check savefile type below */
6262 err = FSpGetFInfo(&myFSS, &myFileInfo);
6265 sprintf(foo, "Arg! FSpGetFInfo failed with code %d", err);
6270 /* Ignore non 'SAVE' files */
6271 if (myFileInfo.fdType != 'SAVE') return noErr;
6273 #ifdef MACH_O_CARBON
6275 /* Extract a file name */
6276 (void)spec_to_path(&myFSS, savefile, sizeof(savefile));
6280 /* XXX XXX XXX Extract a file name */
6281 PathNameFromDirID(myFSS.parID, myFSS.vRefNum, (StringPtr)savefile);
6282 pstrcat((StringPtr)savefile, (StringPtr)&myFSS.name);
6284 /* Convert the string */
6285 ptocstr((StringPtr)savefile);
6287 #endif /* MACH_O_CARBON */
6289 /* Delay actual open */
6290 open_when_ready = TRUE;
6293 err = AEDisposeDesc(&docList);
6305 * Macintosh modifiers (event.modifier & ccc):
6306 * cmdKey, optionKey, shiftKey, alphaLock, controlKey
6309 * Macintosh Keycodes (0-63 normal, 64-95 keypad, 96-127 extra):
6354 * Optimize non-blocking calls to "CheckEvents()"
6355 * Idea from "Maarten Hazewinkel <mmhazewi@cs.ruu.nl>"
6357 #define EVENT_TICKS 6
6361 * Check for Events, return TRUE if we process any
6363 * Hack -- Handle AppleEvents if appropriate (ignore result code).
6365 static bool CheckEvents(bool wait)
6381 term_data *td = NULL;
6385 static huge lastTicks = 0L;
6388 /* Access the clock */
6389 curTicks = TickCount();
6391 /* Hack -- Allow efficient checking for non-pending events */
6392 if (!wait && (curTicks < lastTicks + EVENT_TICKS)) return (FALSE);
6394 /* Timestamp last check */
6395 lastTicks = curTicks;
6397 #if TARGET_API_MAC_CARBON
6398 WaitNextEvent( everyEvent, &event, 1L, nil );
6400 /* Let the "system" run */
6403 /* Get an event (or null) */
6404 GetNextEvent(everyEvent, &event);
6407 /* Hack -- Nothing is ready yet */
6408 if (event.what == nullEvent) return (FALSE);
6410 /* Analyze the event */
6418 w = (WindowPtr)event.message;
6429 /* Extract the window */
6430 w = (WindowPtr)event.message;
6432 /* Find the window */
6433 for (i = 0; i < MAX_TERM_DATA; i++)
6435 /* Skip dead windows */
6436 if (!data[i].t) continue;
6438 /* Notice matches */
6439 if (data[i].w == w) td = &data[i];
6442 /* Hack XXX XXX XXX */
6446 /* Redraw the window */
6447 if (td) term_data_redraw(td);
6455 /* Extract some modifiers */
6456 mc = (event.modifiers & controlKey) ? TRUE : FALSE;
6457 ms = (event.modifiers & shiftKey) ? TRUE : FALSE;
6458 mo = (event.modifiers & optionKey) ? TRUE : FALSE;
6459 mx = (event.modifiers & cmdKey) ? TRUE : FALSE;
6461 /* Keypress: (only "valid" if ck < 96) */
6462 ch = (event.message & charCodeMask) & 255;
6464 /* Keycode: see table above */
6465 ck = ((event.message & keyCodeMask) >> 8) & 255;
6467 /* Command + "normal key" -> menu action */
6468 if (mx && (ck < 64))
6470 /* Hack -- Prepare the menus */
6473 /* Run the Menu-Handler */
6476 /* Turn off the menus */
6484 /* Hide the mouse pointer */
6487 /* Normal key -> simple keypress */
6490 /* Enqueue the keypress */
6494 /* Bizarre key -> encoded keypress */
6497 /* Hack -- introduce with control-underscore */
6500 /* Send some modifier keys */
6501 if (mc) Term_keypress('C');
6502 if (ms) Term_keypress('S');
6503 if (mo) Term_keypress('O');
6504 if (mx) Term_keypress('X');
6506 /* Hack -- Downshift and encode the keycode */
6507 Term_keypress('0' + (ck - 64) / 10);
6508 Term_keypress('0' + (ck - 64) % 10);
6510 /* Hack -- Terminate the sequence */
6511 /* MPW can generate 10 or 13 for keycode of '\r' */
6512 /* -noMapCR option swaps '\r' and '\n' */
6513 Term_keypress('\r');
6523 /* Analyze click location */
6524 code = FindWindow(event.where, &w);
6526 /* Find the window */
6527 for (i = 0; i < MAX_TERM_DATA; i++)
6529 /* Skip dead windows */
6530 if (!data[i].t) continue;
6532 /* Notice matches */
6533 if (data[i].w == w) td = &data[i];
6542 menu(MenuSelect(event.where));
6546 #if !TARGET_API_MAC_CARBON
6549 SystemClick(&event, w);
6561 #if TARGET_API_MAC_CARBON
6562 GetQDGlobalsScreenBits( &screen );
6564 screen = qd.screenBits;
6567 r.top += 20; /* GetMBarHeight() XXX XXX XXX */
6568 InsetRect(&r, 4, 4);
6569 DragWindow(w, event.where, &r);
6581 #if TARGET_API_MAC_CARBON
6582 GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &portRect );
6584 portRect = td->w->portRect;
6585 local_to_global( &portRect );
6587 p.h = portRect.left;
6589 #if !TARGET_API_MAC_CARBON
6598 /* Apply and Verify */
6599 term_data_check_size(td);
6609 /* Track the go-away box */
6610 if (TrackGoAway(w, event.where))
6616 td->t->mapped_flag = FALSE;
6618 /* Hide the window */
6632 #if TARGET_API_MAC_CARBON
6633 GetQDGlobalsScreenBits( &screen );
6635 screen = qd.screenBits;
6640 /* Fake rectangle */
6641 r.left = 20 * td->tile_wid + td->size_ow1;
6642 r.right = screen.bounds.right;
6643 r.top = 1 * td->tile_hgt + td->size_oh1;
6644 r.bottom = screen.bounds.bottom;
6646 /* Grow the rectangle */
6647 newsize = GrowWindow(w, event.where, &r);
6650 if (!newsize) break;
6652 /* Extract the new size in pixels */
6653 y = HiWord(newsize) - td->size_oh1 - td->size_oh2;
6654 x = LoWord(newsize) - td->size_ow1 - td->size_ow2;
6656 /* Extract a "close" approximation */
6657 td->rows = y / td->tile_hgt;
6658 td->cols = x / td->tile_wid;
6660 /* Apply and Verify */
6661 term_data_check_size(td);
6663 Term_activate(td->t);
6665 /* Hack -- Resize the term */
6666 Term_resize(td->cols, td->rows);
6668 /* Resize and Redraw */
6669 term_data_resize(td);
6670 term_data_redraw(td);
6689 /* Disk Event -- From "Maarten Hazewinkel" */
6693 #if TARGET_API_MAC_CARBON
6695 /* check for error when mounting the disk */
6696 if (HiWord(event.message) != noErr)
6702 DIBadMount(p, event.message);
6709 /* OS Event -- From "Maarten Hazewinkel" */
6712 switch ((event.message >> 24) & 0x000000FF)
6714 case suspendResumeMessage:
6716 /* Resuming: activate the front window */
6717 if (event.message & resumeFlag)
6719 #if TARGET_API_MAC_CARBON
6722 SetPortWindowPort( FrontWindow() );
6724 GetQDGlobalsArrow( &arrow );
6727 SetPort(FrontWindow());
6728 SetCursor(&qd.arrow);
6732 /* Suspend: deactivate the front window */
6746 /* From "Steve Linberg" and "Maarten Hazewinkel" */
6747 case kHighLevelEvent:
6749 #if TARGET_API_MAC_CARBON
6750 AEProcessAppleEvent(&event);
6752 /* Process apple events */
6753 if (AEProcessAppleEvent(&event) != noErr)
6756 plog("Apple Event Handlerのエラーです.");
6758 plog("Error in Apple Event Handler!");
6762 /* Handle "quit_when_ready" */
6763 if (quit_when_ready)
6766 quit_when_ready = FALSE;
6768 /* Do the menu key */
6771 /* Turn off the menus */
6775 /* Handle "open_when_ready" */
6776 handle_open_when_ready();
6787 /* Something happened */
6794 /*** Some Hooks for various routines ***/
6798 * Mega-Hack -- emergency lifeboat
6800 static vptr lifeboat = NULL;
6804 * Hook to "release" memory
6806 static vptr hook_rnfree(vptr v, huge size)
6809 #pragma unused (size)
6813 /* Alternative method */
6828 * Hook to "allocate" memory
6830 static vptr hook_ralloc(huge size)
6835 /* Make a new pointer */
6836 return (malloc(size));
6840 /* Make a new pointer */
6841 return (NewPtr(size));
6848 * Hook to handle "out of memory" errors
6850 static vptr hook_rpanic(huge size)
6853 #pragma unused (size)
6855 /* vptr mem = NULL; */
6857 /* Free the lifeboat */
6860 /* Free the lifeboat */
6861 DisposePtr(lifeboat);
6863 /* Forget the lifeboat */
6866 /* Mega-Hack -- Warning */
6868 mac_warning("メモリーが足りません!\r今すぐ終了して下さい!");
6870 mac_warning("Running out of Memory!\rAbort this process now!");
6873 /* Mega-Hack -- Never leave this function */
6874 while (TRUE) CheckEvents(TRUE);
6877 /* Mega-Hack -- Crash */
6883 * Hook to tell the user something important
6885 static void hook_plog(cptr str)
6887 /* Warning message */
6892 * Hook to tell the user something, and then quit
6894 static void hook_quit(cptr str)
6896 /* Warning if needed */
6897 if (str) mac_warning(str);
6899 #ifdef USE_ASYNC_SOUND
6901 /* Clean up sound support */
6904 #endif /* USE_ASYNC_SOUND */
6906 /* Write a preference file */
6914 * Hook to tell the user something, and then crash
6916 static void hook_core(cptr str)
6918 /* XXX Use the debugger */
6919 /* DebugStr(str); */
6922 if (str) mac_warning(str);
6924 /* Warn, then save player */
6926 mac_warning("致命的なエラーです.\r強制的にセーブして終了します.");
6928 mac_warning("Fatal error.\rI will now attempt to save and quit.");
6931 /* Attempt to save */
6933 if (!save_player()) mac_warning("警告 -- セーブに失敗しました!");
6935 if (!save_player()) mac_warning("Warning -- save failed!");
6944 /*** Main program ***/
6950 * XXX XXX XXX Hack -- This function attempts to "fix" the nasty
6951 * "Macintosh Save Bug" by using "absolute" path names, since on
6952 * System 7 machines anyway, the "current working directory" often
6953 * "changes" due to background processes, invalidating any "relative"
6954 * path names. Note that the Macintosh is limited to 255 character
6955 * path names, so be careful about deeply embedded directories...
6957 * XXX XXX XXX Hack -- This function attempts to "fix" the nasty
6958 * "missing lib folder bug" by allowing the user to help find the
6959 * "lib" folder by hand if the "application folder" code fails...
6961 static void init_stuff(void)
6965 #if !TARGET_API_MAC_CARBON
6982 #if TARGET_API_MAC_CARBON
6984 NavDialogOptions dialogOptions;
6985 FSSpec theFolderSpec;
6986 NavReplyRecord theReply;
6988 /* Fake rectangle */
6995 #if TARGET_API_MAC_CARBON
6996 screenRect = GetQDGlobalsScreenBits(&screen)->bounds;
6998 screenRect = qd.screenBits.bounds;
7000 center_rect(&r, &screenRect);
7002 /* Extract corner */
7007 /* Default to the "lib" folder with the application */
7008 #ifdef MACH_O_CARBON
7009 if (locate_lib(path, sizeof(path)) == NULL) quit(NULL);
7011 refnum_to_name(path, app_dir, app_vol, (char*)("\plib:"));
7015 /* Check until done */
7018 /* Prepare the paths */
7019 init_file_paths(path);
7021 /* Build the filename */
7022 path_build(path, sizeof(path), ANGBAND_DIR_FILE, _("news_j.txt", "news.txt"));
7024 /* Attempt to open and close that file */
7025 if (0 == fd_close(fd_open(path, O_RDONLY))) break;
7028 plog_fmt(_("'%s' ファイルをオープン出来ません.", "Unable to open the '%s' file."), path);
7031 plog(_("Hengbandの'lib'フォルダが存在しないか正しく無い可能性があります.", "The Angband 'lib' folder is probably missing or misplaced."));
7034 plog(_("Please 'open' any file in any sub-folder of the 'lib' folder.", "Please 'open' any file in any sub-folder of the 'lib' folder."));
7036 #if TARGET_API_MAC_CARBON
7037 /* Ask the user to choose the lib folder */
7038 err = NavGetDefaultDialogOptions(&dialogOptions);
7041 if (err != noErr) quit(NULL);
7043 /* Set default location option */
7044 dialogOptions.dialogOptionFlags |= kNavSelectDefaultLocation;
7046 /* Clear preview option */
7047 dialogOptions.dialogOptionFlags &= ~(kNavAllowPreviews);
7049 /* Forbit selection of multiple files */
7050 dialogOptions.dialogOptionFlags &= ~(kNavAllowMultipleFiles);
7052 /* Display location */
7053 dialogOptions.location = topleft;
7055 /* Load the message for the missing folder from the resource fork */
7056 GetIndString(dialogOptions.message, 128, 1);
7058 /* Wait for the user to choose a folder */
7059 err = NavChooseFolder(
7067 /* Assume the player doesn't want to go on */
7068 if ((err != noErr) || !theReply.validRecord) quit(NULL);
7070 /* Retrieve FSSpec from the reply */
7072 AEKeyword theKeyword;
7073 DescType actualType;
7076 /* Get a pointer to selected folder */
7078 &(theReply.selection),
7088 if (err != noErr) quit(NULL);
7091 /* Free navitagor reply */
7092 err = NavDisposeReply(&theReply);
7095 if (err != noErr) quit(NULL);
7097 /* Extract textual file name for given file */
7100 theFolderSpec.parID,
7101 theFolderSpec.vRefNum,
7102 (char *)theFolderSpec.name);
7104 /* Allow "text" files */
7107 /* Allow "save" files */
7110 /* Allow "data" files */
7114 SFGetFile(topleft, "\p", NULL, 3, types, NULL, &reply);
7117 if (!reply.good) quit(NULL);
7119 /* Extract textual file name for given file */
7120 GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
7121 refnum_to_name(path, drefnum, vrefnum, (char*)reply.fName);
7124 /* Hack -- Remove the "filename" */
7125 i = strlen(path) - 1;
7126 while ((i > 0) && (path[i] != ':')) i--;
7127 if (path[i] == ':') path[i+1] = '\0';
7129 /* Hack -- allow "lib" folders */
7130 if (suffix(path, "lib:")) continue;
7132 /* Hack -- Remove the "sub-folder" */
7134 while ((i > 1) && (path[i] != ':')) i--;
7135 if (path[i] == ':') path[i+1] = '\0';
7141 * Macintosh Main loop
7145 EventRecord tempEvent;
7146 int numberOfMasters = 10;
7148 #if !TARGET_API_MAC_CARBON
7149 /* Increase stack space by 64K */
7150 SetApplLimit(GetApplLimit() - 131072L);//65536L);
7152 /* Stretch out the heap to full size */
7156 /* Get more Masters */
7157 while (numberOfMasters--) MoreMasters();
7159 #if !TARGET_API_MAC_CARBON
7160 /* Set up the Macintosh */
7161 InitGraf(&qd.thePort);
7175 FlushEvents(everyEvent, 0);
7177 /* Flush events some more (?) */
7178 (void)EventAvail(everyEvent, &tempEvent);
7179 (void)EventAvail(everyEvent, &tempEvent);
7180 (void)EventAvail(everyEvent, &tempEvent);
7183 #ifdef ANGBAND_LITE_MAC
7187 #else /* ANGBAND_LITE_MAC */
7189 # if defined(powerc) || defined(__powerc)
7191 /* Assume System 7 */
7193 /* Assume Color Quickdraw */
7197 #if TARGET_API_MAC_CARBON
7203 /* Check for existence of Carbon */
7204 err = Gestalt(gestaltCarbonVersion, &response);
7206 if (err != noErr) quit("This program requires Carbon API");
7216 /* Check the Gestalt */
7217 err = Gestalt(gestaltSystemVersion, &versionNumber);
7219 /* Check the version */
7220 if ((err != noErr) || (versionNumber < 0x0700))
7223 quit("このプログラムは漢字Talk7.x.x以降で動作します.");
7225 quit("You must have System 7 to use this program.");
7235 /* Check the environs */
7236 if (SysEnvirons(1, &env) != noErr)
7239 quit("SysEnvirons コールは失敗しました!");
7241 quit("The SysEnvirons call failed!");
7245 /* Check for System Seven Stuff */
7246 if (env.systemVersion < 0x0700)
7249 quit("このプログラムは漢字Talk7.x.x以降で動作します.");
7251 quit("You must have System 7 to use this program.");
7255 /* Check for Color Quickdraw */
7256 if (!env.hasColorQD)
7259 quit("このプログラムはColor Quickdrawが無いと動作しません.");
7261 quit("You must have Color Quickdraw to use this program.");
7269 #endif /* ANGBAND_LITE_MAC */
7272 * Remember Mac OS version, in case we have to cope with version-specific
7275 (void)Gestalt(gestaltSystemVersion, &mac_os_version);
7278 /* Obtain a "Universal Procedure Pointer" */
7279 AEH_Start_UPP = NewAEEventHandlerUPP(AEH_Start);
7280 /* Install the hook (ignore error codes) */
7281 AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, AEH_Start_UPP,
7284 /* Obtain a "Universal Procedure Pointer" */
7285 AEH_Quit_UPP = NewAEEventHandlerUPP(AEH_Quit);
7286 /* Install the hook (ignore error codes) */
7287 AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, AEH_Quit_UPP,
7290 /* Obtain a "Universal Procedure Pointer" */
7291 AEH_Print_UPP = NewAEEventHandlerUPP(AEH_Print);
7292 /* Install the hook (ignore error codes) */
7293 AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, AEH_Print_UPP,
7296 /* Obtain a "Universal Procedure Pointer" */
7297 AEH_Open_UPP = NewAEEventHandlerUPP(AEH_Open);
7298 /* Install the hook (ignore error codes) */
7299 AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, AEH_Open_UPP,
7303 #ifndef MACH_O_CARBON
7304 /* Find the current application */
7308 /* Mark ourself as the file creator */
7309 _fcreator = ANGBAND_CREATOR;
7311 /* Default to saving a "text" file */
7315 #if defined(__MWERKS__)
7317 /* Obtian a "Universal Procedure Pointer" */
7318 #if TARGET_API_MAC_CARBON
7319 ynfilterUPP = NewModalFilterUPP(ynfilter);
7321 ynfilterUPP = NewModalFilterProc(ynfilter);
7327 /* Hook in some "z-virt.c" hooks */
7328 rnfree_aux = hook_rnfree;
7329 ralloc_aux = hook_ralloc;
7330 rpanic_aux = hook_rpanic;
7332 /* Hooks in some "z-util.c" hooks */
7333 plog_aux = hook_plog;
7334 quit_aux = hook_quit;
7335 core_aux = hook_core;
7337 BackColor(blackColor);
7338 ForeColor(whiteColor);
7340 /* Show the "watch" cursor */
7341 SetCursor(*(GetCursor(watchCursor)));
7343 /* Prepare the menubar */
7346 /* Prepare the windows */
7349 #ifndef MACH_O_CARBON
7357 /* Hack -- process all events */
7358 while (CheckEvents(TRUE)) /* loop */;
7360 /* Reset the cursor */
7361 #if TARGET_API_MAC_CARBON
7364 GetQDGlobalsArrow( &arrow );
7368 SetCursor( &qd.arrow );
7372 /* Mega-Hack -- Allocate a "lifeboat" */
7373 lifeboat = NewPtr(16384);
7377 /* Load sound effect resources */
7380 #endif /* USE_QT_SOUND */
7382 /* Note the "system" */
7383 ANGBAND_SYS = "mac";
7388 /* Catch nasty signals */
7395 /* Hack -- process all events */
7396 while (CheckEvents(TRUE)) /* loop */;
7399 /* We are now initialized */
7403 /* Handle "open_when_ready" */
7404 handle_open_when_ready();
7410 /* Prompt the user */
7411 prt(_("'ファイル'メニューより'新規'または'開く...'を選択してください。", "[Choose 'New' or 'Open' from the 'File' menu]"), 23, _(10, 15));
7413 /* Flush the prompt */
7417 /* Hack -- Process Events Forever */
7418 while (TRUE) CheckEvents(TRUE);