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
189 #define PREF_FILE_NAME "Hengband Preferences"
191 #define PREF_FILE_NAME "Hengband-E Preferences"
195 * Use "malloc()" instead of "NewPtr()"
197 /* #define USE_MALLOC */
200 /* Default creator signature */
201 #ifndef ANGBAND_CREATOR
202 # define ANGBAND_CREATOR 'Heng'
206 #if defined(powerc) || defined(__powerc)
209 * Disable "LITE" version
211 # undef ANGBAND_LITE_MAC
216 #ifdef ANGBAND_LITE_MAC
219 * Maximum number of windows
221 # define MAX_TERM_DATA 1
223 #else /* ANGBAND_LITE_MAC */
226 * Maximum number of windows
228 # define MAX_TERM_DATA 8
231 * Activate some special code
233 # define USE_SFL_CODE
236 * Use rewritten asynchronous sound player
238 #define USE_ASYNC_SOUND
245 #endif /* MACH_O_CARBON */
246 #endif /* ANGBAND_LITE_MAC */
250 #ifndef MACH_O_CARBON
254 * Include the necessary header files
256 #include <AppleEvents.h>
261 #endif /* !MACH_O_CARBON */
264 * Globals for MPW compilation
266 #if defined(MACH_O_CARBON) || defined(MAC_MPW)
268 #if !TARGET_API_MAC_CARBON
280 * The Angband Color Set (0 to 15):
281 * Black, White, Slate, Orange, Red, Blue, Green, Umber
282 * D-Gray, L-Gray, Violet, Yellow, L-Red, L-Blue, L-Green, L-Umber
284 * Colors 8 to 15 are basically "enhanced" versions of Colors 0 to 7.
286 * On the Macintosh, we use color quickdraw, and we use actual "RGB"
287 * values below to choose the 16 colors.
289 * If we are compiled for ancient machines, we bypass color and simply
290 * draw everything in white (letting "z-term.c" automatically convert
291 * "black" into "wipe" calls).
293 static RGBColor foo[16] =
295 {0x0000, 0x0000, 0x0000}, /* TERM_DARK */
296 {0xFFFF, 0xFFFF, 0xFFFF}, /* TERM_WHITE */
297 {0x8080, 0x8080, 0x8080}, /* TERM_SLATE */
298 {0xFFFF, 0x8080, 0x0000}, /* TERM_ORANGE */
299 {0xC0C0, 0x0000, 0x0000}, /* TERM_RED */
300 {0x0000, 0x8080, 0x4040}, /* TERM_GREEN */
301 {0x0000, 0x0000, 0xFFFF}, /* TERM_BLUE */
302 {0x8080, 0x4040, 0x0000}, /* TERM_UMBER */
303 {0x4040, 0x4040, 0x4040}, /* TERM_L_DARK */
304 {0xC0C0, 0xC0C0, 0xC0C0}, /* TERM_L_WHITE */
305 {0xFFFF, 0x0000, 0xFFFF}, /* TERM_VIOLET */
306 {0xFFFF, 0xFFFF, 0x0000}, /* TERM_YELLOW */
307 {0xFFFF, 0x0000, 0x0000}, /* TERM_L_RED */
308 {0x0000, 0xFFFF, 0x0000}, /* TERM_L_GREEN */
309 {0x0000, 0xFFFF, 0xFFFF}, /* TERM_L_BLUE */
310 {0xC0C0, 0x8080, 0x4040} /* TERM_L_UMBER */
319 typedef struct term_data term_data;
332 #ifdef ANGBAND_LITE_MAC
336 #else /* ANGBAND_LITE_MAC */
348 #endif /* ANGBAND_LITE_MAC */
391 * Forward declare -- see below
393 static bool CheckEvents(bool wait);
395 #ifndef MACH_O_CARBON
398 * Hack -- location of the main directory
400 static short app_vol;
403 #endif /* !MACH_O_CARBON */
406 * Delay handling of double-clicked savefiles
408 Boolean open_when_ready = FALSE;
411 * Delay handling of pre-emptive "quit" event
413 Boolean quit_when_ready = FALSE;
417 * Hack -- game in progress
419 static int game_in_progress = 0;
423 * Only do "SetPort()" when needed
425 static WindowPtr active = NULL;
430 * An array of term_data's
432 static term_data data[MAX_TERM_DATA];
437 * Note when "open"/"new" become valid
439 static bool initialized = FALSE;
442 * Version of Mac OS - for version specific bug workarounds (; ;)
444 static long mac_os_version;
447 #if defined(__MWERKS__)
449 * CodeWarrior uses Universal Procedure Pointers
451 static ModalFilterUPP ynfilterUPP;
453 #endif /* __MWERKS__ */
460 AEEventHandlerUPP AEH_Start_UPP;
461 AEEventHandlerUPP AEH_Quit_UPP;
462 AEEventHandlerUPP AEH_Print_UPP;
463 AEEventHandlerUPP AEH_Open_UPP;
468 * Convert refnum+vrefnum+fname into a full file name
469 * Store this filename in 'buf' (make sure it is long enough)
470 * Note that 'fname' looks to be a "pascal" string
472 #if TARGET_API_MAC_CARBON
473 static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname)
488 for (j=1; j<=fname[0]; j++)
490 res[i-fname[0]+j] = fname[j];
499 pb.dirInfo.ioDrDirID=pb.dirInfo.ioDrParID;
500 err = FSMakeFSSpec( vref, dirID, "\p", &spec );
506 for (j=1; j<=spec.name[0]; j++)
508 res[i-spec.name[0]+j] = spec.name[j];
515 /* Extract the result */
516 for (j = 0, i++; res[i]; j++, i++) buf[j] = res[i];
520 static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname)
532 for (j=1; j<=fname[0]; j++)
534 res[i-fname[0]+j] = fname[j];
538 pb.ioCompletion=NULL;
540 pb.ioVRefNum=vrefnum;
546 pb.ioDrDirID=pb.ioDrParID;
547 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
549 for (j=1; j<=name[0]; j++)
551 res[i-name[0]+j] = name[j];
555 if (pb.ioDrDirID == fsRtDirID) break;
558 /* Extract the result */
559 for (j = 0, i++; res[i]; j++, i++) buf[j] = res[i];
564 #if TARGET_API_MAC_CARBON
565 pascal OSErr FSpLocationFromFullPath(short fullPathLength,
566 const void *fullPath,
574 /* Create a minimal alias from the full pathname */
575 nullString[0] = 0; /* null string to indicate no zone or server name */
576 result = NewAliasMinimalFromFullPath(fullPathLength, fullPath, nullString, nullString, &alias);
577 if ( result == noErr )
579 /* Let the Alias Manager resolve the alias. */
580 result = ResolveAlias(NULL, alias, spec, &wasChanged);
582 /* work around Alias Mgr sloppy volume matching bug */
583 if ( spec->vRefNum == 0 )
585 /* invalidate wrong FSSpec */
590 DisposeHandle((Handle)alias); /* Free up memory used */
599 * XXX XXX XXX Allow the system to ask us for a filename
601 static bool askfor_file(char *buf, int len)
609 /* Default file name */
610 sprintf((char*)dflt + 1, "%s's description", buf);
611 dflt[0] = strlen((char*)dflt + 1);
613 /* Ask for a file name */
614 topleft.h=(qd.screenBits.bounds.left+qd.screenBits.bounds.right)/2-344/2;
615 topleft.v=(2*qd.screenBits.bounds.top+qd.screenBits.bounds.bottom)/3-188/2;
616 SFPutFile(topleft, "\pSelect a filename:", dflt, NULL, &reply);
617 /* StandardPutFile("\pSelect a filename:", dflt, &reply); */
625 GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
627 /* Extract the name */
628 refnum_to_name(buf, drefnum, vrefnum, (char*)reply.fName);
640 #if !TARGET_API_MAC_CARBON
641 static void local_to_global( Rect *r )
648 LocalToGlobal( &temp );
656 LocalToGlobal( &temp );
661 #endif /* !TARGET_API_MAC_CARBON */
663 static void global_to_local( Rect *r )
670 GlobalToLocal( &temp );
678 GlobalToLocal( &temp );
688 * Convert pathname to an appropriate format, because MPW's
689 * CarbonStdCLib chose to use system's native path format,
690 * making our lives harder to create binaries that run on
691 * OS 8/9 and OS X :( -- pelpel
693 void convert_pathname(char* path)
697 /* Nothing has to be done for CarbonLib on Classic */
698 if (mac_os_version >= 0x1000)
700 /* Convert to POSIX style */
701 ConvertHFSPathToUnixPath(path, buf);
703 /* Copy the result back */
711 # ifdef CHECK_MODIFICATION_TIME
714 * Although there is no easy way to emulate fstat in the old interface,
715 * we still can do stat-like things, because Mac OS is an OS.
717 static int get_modification_time(cptr path, u32b *mod_time)
723 /* Paranoia - make sure the pathname fits in Str255 */
725 if (i > 255) return (-1);
727 /* Convert pathname to a Pascal string */
728 strncpy((char *)pathname + 1, path, 255);
731 /* Set up parameter block */
732 pb.hFileInfo.ioNamePtr = pathname;
733 pb.hFileInfo.ioFDirIndex = 0;
734 pb.hFileInfo.ioVRefNum = app_vol;
735 pb.hFileInfo.ioDirID = 0;
737 /* Get catalog information of the file */
738 if (PBGetCatInfoSync(&pb) != noErr) return (-1);
740 /* Set modification date and time */
741 *mod_time = pb.hFileInfo.ioFlMdDat;
749 * A (non-Mach-O) Mac OS version of check_modification_time, for those
750 * compilers without good enough POSIX-compatibility libraries XXX XXX
752 errr check_modification_date(int fd, cptr template_file)
755 u32b txt_stat, raw_stat;
760 /* Build the file name */
761 path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, template_file);
764 convert_pathname(buf);
766 /* Obtain modification time */
767 if (get_modification_time(buf, &txt_stat)) return (-1);
769 /* XXX Build filename of the corresponding *.raw file */
770 strnfmt(fname, sizeof(fname), "%s", template_file);
773 p = strrchr(fname, '.');
776 if (p == NULL) return (-1);
778 /* Substitute ".raw" for ".txt" */
781 /* Build the file name of the raw file */
782 path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, fname);
785 convert_pathname(buf);
787 /* Obtain modification time */
788 if (get_modification_time(buf, &raw_stat)) return (-1);
790 /* Ensure the text file is not newer than the raw file */
791 if (txt_stat > raw_stat) return (-1);
793 /* Keep using the current .raw file */
797 # endif /* CHECK_MODIFICATION_TIME */
802 * Center a rectangle inside another rectangle
804 static void center_rect(Rect *r, Rect *s)
806 int centerx = (s->left + s->right)/2;
807 int centery = (2*s->top + s->bottom)/3;
808 int dx = centerx - (r->right - r->left)/2 - r->left;
809 int dy = centery - (r->bottom - r->top)/2 - r->top;
819 /* Carbon File Manager utilities by pelpel */
823 * Convert a pathname to a corresponding FSSpec.
824 * Returns noErr on success.
826 static OSErr path_to_spec(const char *path, FSSpec *spec)
831 /* Convert pathname to FSRef ... */
832 err = FSPathMakeRef(path, &ref, NULL);
833 if (err != noErr) return (err);
835 /* ... then FSRef to FSSpec */
836 err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
838 /* Inform caller of success or failure */
845 * Convert a FSSpec to a corresponding pathname.
846 * Returns noErr on success.
848 static OSErr spec_to_path(const FSSpec *spec, char *buf, size_t size)
853 /* Convert FSSpec to FSRef ... */
854 err = FSpMakeFSRef(spec, &ref);
855 if (err != noErr) return (err);
857 /* ... then FSRef to pathname */
858 err = FSRefMakePath(&ref, buf, size);
860 /* Inform caller of success or failure */
866 * (Carbon) [via path_to_spec]
867 * Set creator and filetype of a file specified by POSIX-style pathname.
868 * Returns 0 on success, -1 in case of errors.
870 void fsetfileinfo(cptr pathname, OSType fcreator, OSType ftype)
876 /* Convert pathname to FSSpec */
877 if (path_to_spec(pathname, &spec) != noErr) return;
879 /* Obtain current finder info of the file */
880 if (FSpGetFInfo(&spec, &info) != noErr) return;
882 /* Overwrite creator and type */
883 info.fdCreator = fcreator;
885 err = FSpSetFInfo(&spec, &info);
892 #else /* MACH_O_CARBON */
896 * Convert a pascal string in place
898 * This function may be defined elsewhere, but since it is so
899 * small, it is not worth finding the proper function name for
900 * all the different platforms.
902 static void ptocstr(StringPtr src)
906 /* Hack -- pointer */
907 char *s = (char*)(src);
909 /* Hack -- convert the string */
910 for (i = s[0]; i; i--, s++) s[0] = s[1];
912 /* Hack -- terminate the string */
917 #if defined(USE_SFL_CODE)
921 * The following three routines (pstrcat, pstrinsert, and PathNameFromDirID)
922 * were taken from the Think Reference section called "Getting a Full Pathname"
923 * (under the File Manager section). We need PathNameFromDirID to get the
924 * full pathname of the opened savefile, making no assumptions about where it
927 * I had to hack PathNameFromDirID a little for MetroWerks, but it's awfully
930 static void pstrcat(StringPtr dst, StringPtr src)
933 BlockMove(src + 1, dst + *dst + 1, *src);
935 /* adjust length byte */
940 * pstrinsert - insert string 'src' at beginning of string 'dst'
942 static void pstrinsert(StringPtr dst, StringPtr src)
944 /* make room for new string */
945 BlockMove(dst + 1, dst + *src + 1, *dst);
947 /* copy new string in */
948 BlockMove(src + 1, dst + 1, *src);
950 /* adjust length byte */
954 static void PathNameFromDirID(long dirID, short vRefNum, StringPtr fullPathName)
957 Str255 directoryName;
960 fullPathName[0] = '\0';
962 block.dirInfo.ioDrParID = dirID;
963 block.dirInfo.ioNamePtr = directoryName;
967 block.dirInfo.ioVRefNum = vRefNum;
968 block.dirInfo.ioFDirIndex = -1;
969 block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID;
970 err = PBGetCatInfo(&block, FALSE);
971 pstrcat(directoryName, (StringPtr)"\p:");
972 pstrinsert(fullPathName, directoryName);
973 if (block.dirInfo.ioDrDirID == 2) break;
978 #endif /* MACH_O_CARBON */
981 * Activate a given window, if necessary
983 static void activate(WindowPtr w)
989 #if TARGET_API_MAC_CARBON
990 if (w) SetPortWindowPort(w);
1002 * Display a warning message
1004 static void mac_warning(cptr warning)
1009 /* Limit of 250 chars */
1010 len = strlen(warning);
1011 if (len > 250) len = 250;
1013 /* Make a "Pascal" string */
1015 for (i=0; i<len; i++) text[i+1] = warning[i];
1017 /* Prepare the dialog box values */
1018 ParamText(text, "\p", "\p", "\p");
1020 /* Display the Alert, wait for Okay */
1026 /*** Some generic functions ***/
1029 #ifdef ANGBAND_LITE_MAC
1032 * Hack -- activate a color (0 to 255)
1034 #define term_data_color(TD,A) /* Nothing */
1036 #else /* ANGBAND_LITE_MAC */
1039 * Hack -- activate a color (0 to 255)
1041 static void term_data_color(term_data *td, int a)
1047 /* Extract the R,G,B data */
1048 rv = angband_color_table[a][1];
1049 gv = angband_color_table[a][2];
1050 bv = angband_color_table[a][3];
1053 color.red = (rv | (rv << 8));
1054 color.green = (gv | (gv << 8));
1055 color.blue = (bv | (bv << 8));
1057 /* Activate the color */
1058 RGBForeColor(&color);
1060 /* Memorize color */
1064 #endif /* ANGBAND_LITE_MAC */
1068 * Hack -- Apply and Verify the "font" info
1070 * This should usually be followed by "term_data_check_size()"
1072 static void term_data_check_font(term_data *td)
1078 WindowPtr old = active;
1084 /* Instantiate font */
1085 TextFont(td->font_id);
1086 TextSize(td->font_size);
1087 TextFace(td->font_face);
1089 /* Extract the font info */
1092 /* Assume monospaced */
1093 td->font_mono = TRUE;
1095 /* Extract the font sizing values XXX XXX XXX */
1096 td->font_wid = CharWidth('@'); /* info.widMax; */
1097 td->font_hgt = info.ascent + info.descent;
1099 td->font_o_y = info.ascent;
1101 /* Check important characters */
1102 for (i = 33; i < 127; i++)
1104 /* Hack -- notice non-mono-space */
1105 if (td->font_wid != CharWidth(i)) td->font_mono = FALSE;
1107 /* Hack -- collect largest width */
1108 if (td->font_wid < CharWidth(i)) td->font_wid = CharWidth(i);
1111 /* Set default offsets */
1112 td->tile_o_x = td->font_o_x;
1113 td->tile_o_y = td->font_o_y;
1115 /* Set default tile size */
1116 if( td->tile_wid == 0 && td->tile_hgt == 0 ){
1117 td->tile_wid = td->font_wid;
1118 td->tile_hgt = td->font_hgt;
1121 /* Re-activate the old window */
1127 * Hack -- Apply and Verify the "size" info
1129 static void term_data_check_size(term_data *td)
1133 #if TARGET_API_MAC_CARBON
1134 GetQDGlobalsScreenBits( &screen );
1136 screen = qd.screenBits;
1138 /* Minimal window size */
1141 /* Enforce minimal size */
1142 if (td->cols < 80) td->cols = 80;
1143 if (td->rows < 24) td->rows = 24;
1146 /* Allow small windows for the rest */
1149 if (td->cols < 1) td->cols = 1;
1150 if (td->rows < 1) td->rows = 1;
1153 /* Minimal tile size */
1154 if (td->tile_wid < 4) td->tile_wid = 4;
1155 if (td->tile_hgt < 4) td->tile_hgt = 4;
1157 /* Default tile offsets */
1158 td->tile_o_x = (td->tile_wid - td->font_wid) / 2;
1159 td->tile_o_y = (td->tile_hgt - td->font_hgt) / 2;
1161 /* Minimal tile offsets */
1162 if (td->tile_o_x < 0) td->tile_o_x = 0;
1163 if (td->tile_o_y < 0) td->tile_o_y = 0;
1165 /* Apply font offsets */
1166 td->tile_o_x += td->font_o_x;
1167 td->tile_o_y += td->font_o_y;
1169 /* Calculate full window size */
1170 td->size_wid = td->cols * td->tile_wid + td->size_ow1 + td->size_ow2;
1171 td->size_hgt = td->rows * td->tile_hgt + td->size_oh1 + td->size_oh2;
1173 /* Verify the top */
1174 if (td->r.top > screen.bounds.bottom - td->size_hgt)
1176 td->r.top = screen.bounds.bottom - td->size_hgt;
1179 /* Verify the top */
1180 if (td->r.top < screen.bounds.top + 30)
1182 td->r.top = screen.bounds.top + 30;
1185 /* Verify the left */
1186 if (td->r.left > screen.bounds.right - td->size_wid)
1188 td->r.left = screen.bounds.right - td->size_wid;
1191 /* Verify the left */
1192 if (td->r.left < screen.bounds.left)
1194 td->r.left = screen.bounds.left;
1197 /* Calculate bottom right corner */
1198 td->r.right = td->r.left + td->size_wid;
1199 td->r.bottom = td->r.top + td->size_hgt;
1201 /* Assume no graphics */
1202 td->t->higher_pict = FALSE;
1203 td->t->always_pict = FALSE;
1205 #ifdef ANGBAND_LITE_MAC
1209 #else /* ANGBAND_LITE_MAC */
1211 /* Handle graphics */
1214 /* Use higher_pict whenever possible */
1215 if (td->font_mono) td->t->higher_pict = TRUE;
1217 /* Use always_pict only when necessary */
1218 else td->t->always_pict = TRUE;
1221 #endif /* ANGBAND_LITE_MAC */
1223 /* Fake mono-space */
1224 if (!td->font_mono ||
1225 (td->font_wid != td->tile_wid) ||
1226 (td->font_hgt != td->tile_hgt))
1228 /* Handle fake monospace -- this is SLOW */
1229 if (td->t->higher_pict) td->t->higher_pict = FALSE;
1230 td->t->always_pict = TRUE;
1235 * Hack -- resize a term_data
1237 * This should normally be followed by "term_data_resize()"
1239 static void term_data_resize(term_data *td)
1241 /* Actually resize the window */
1242 SizeWindow(td->w, td->size_wid, td->size_hgt, 0);
1248 * Hack -- redraw a term_data
1250 * Note that "Term_redraw()" calls "TERM_XTRA_CLEAR"
1252 static void term_data_redraw(term_data *td)
1256 /* Activate the term */
1257 Term_activate(td->t);
1259 /* Redraw the contents */
1262 /* Flush the output */
1265 /* Restore the old term */
1268 /* No need to redraw */
1269 #if TARGET_API_MAC_CARBON
1271 RgnHandle theRgn = NewRgn();
1272 GetWindowRegion( td->w, kWindowContentRgn, theRgn );
1273 ValidWindowRgn( (WindowRef)(td->w), theRgn );
1274 DisposeRgn( theRgn );
1277 ValidRect(&td->w->portRect);
1285 #ifdef ANGBAND_LITE_MAC
1289 #else /* ANGBAND_LITE_MAC */
1297 * PICT id of image tiles, set by Term_xtra_mac_react
1299 #ifdef MACH_O_CARBON
1300 static CFStringRef pictID = NULL;
1302 static int pictID = 0;
1303 #endif /* MACH_O_CARBON */
1306 * Width and height of a tile in pixels
1308 static int grafWidth = 0;
1309 static int grafHeight = 0;
1312 * Numbers of rows and columns in tiles, calculated by
1313 * the PICT loading code
1315 static int pictCols = 0;
1316 static int pictRows = 0;
1319 * Available graphics modes - 32x32 tiles don't work on Classic
1321 #define GRAF_MODE_NONE 0
1322 #define GRAF_MODE_8X8 1
1323 #define GRAF_MODE_16X16 2
1324 #define GRAF_MODE_32X32 3
1327 * Current and requested graphics modes
1329 static int graf_mode = GRAF_MODE_NONE;
1330 static int graf_mode_req = GRAF_MODE_NONE;
1336 typedef struct FrameRec FrameRec;
1341 * - GWorld for the frame image
1342 * - Handle to pix map (saved for unlocking/locking)
1343 * - Pointer to color pix map (valid only while locked)
1347 GWorldPtr framePort;
1348 PixMapHandle framePixHndl;
1355 * The global picture data
1357 static FrameRec *frameP = NULL;
1363 static void BenSWLockFrame(FrameRec *srcFrameP)
1365 PixMapHandle pixMapH;
1367 pixMapH = GetGWorldPixMap(srcFrameP->framePort);
1368 (void)LockPixels(pixMapH);
1369 HLockHi((Handle)pixMapH);
1370 srcFrameP->framePixHndl = pixMapH;
1371 #if TARGET_API_MAC_CARBON
1372 srcFrameP->framePix = (PixMapPtr)*(Handle)pixMapH;
1374 srcFrameP->framePix = (PixMapPtr)StripAddress(*(Handle)pixMapH);
1383 static void BenSWUnlockFrame(FrameRec *srcFrameP)
1385 if (srcFrameP->framePort != NULL)
1387 HUnlock((Handle)srcFrameP->framePixHndl);
1388 UnlockPixels(srcFrameP->framePixHndl);
1391 srcFrameP->framePix = NULL;
1395 #ifdef MACH_O_CARBON
1398 * Moving graphics resources into data fork -- pelpel
1401 * Given base and type names of a resource, find a file in the
1402 * current application bundle and return its FSSpec in the third argument.
1403 * Returns true on success, false otherwise.
1404 * e.g. get_resource_spec(CFSTR("8x8"), CFSTR("png"), &spec);
1406 static Boolean get_resource_spec(
1407 CFStringRef base_name, CFStringRef type_name, FSSpec *spec)
1412 /* Find resource (=file) in the current bundle */
1413 res_url = CFBundleCopyResourceURL(
1414 CFBundleGetMainBundle(), base_name, type_name, NULL);
1417 if (res_url == NULL) return (false);
1419 /* Convert CFURL to FSRef */
1420 (void)CFURLGetFSRef(res_url, &ref);
1422 /* Convert FSRef to FSSpec */
1423 (void)FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
1425 /* Free allocated CF data */
1435 * Create a off-screen GWorld from contents of a file specified by a FSSpec.
1436 * Based on BenSWCreateGWorldFromPict.
1438 * Globals referenced: data[0], graf_height, graf_width
1439 * Globals updated: pict_rows, pict_cols.
1441 static OSErr create_gworld_from_spec(
1442 GWorldPtr *tile_gw, FSSpec *tile_spec)
1445 GraphicsImportComponent gi;
1446 GWorldPtr gw, tmp_gw;
1447 GDHandle gdh, tmp_gdh;
1451 /* See if QuickTime understands the file format */
1452 err = GetGraphicsImporterForFile(tile_spec, &gi);
1455 if (err != noErr) return (err);
1458 depth = data[0].pixelDepth;
1461 gdh = data[0].theGDH;
1463 /* Retrieve the rect of the image */
1464 err = GraphicsImportGetNaturalBounds(gi, &r);
1466 /* Adjust it, so that the upper left corner becomes (0, 0) */
1467 OffsetRect(&r, -r.left, -r.top);
1469 /* Calculate and set numbers of rows and columns */
1470 pictRows = r.bottom / grafHeight;
1471 pictCols = r.right / grafWidth;
1473 /* Create a GWorld */
1474 err = NewGWorld(&gw, depth, &r, NULL, gdh, noNewDevice);
1477 if (err != noErr) return (err);
1479 /* Save the pointer to the GWorld */
1482 /* Save the current GWorld */
1483 GetGWorld(&tmp_gw, &tmp_gdh);
1485 /* Activate the newly created GWorld */
1486 (void)GraphicsImportSetGWorld(gi, gw, NULL);
1488 /* Prevent pixmap from moving while drawing */
1489 (void)LockPixels(GetGWorldPixMap(gw));
1491 /* Clear the pixels */
1494 /* Draw the image into it */
1495 (void)GraphicsImportDraw(gi);
1497 /* Release the lock*/
1498 UnlockPixels(GetGWorldPixMap(gw));
1500 /* Restore GWorld */
1501 SetGWorld(tmp_gw, tmp_gdh);
1503 /* Close the image importer */
1510 #else /* MACH_O_CARBON */
1512 static OSErr BenSWCreateGWorldFromPict(
1513 GWorldPtr *pictGWorld,
1517 GWorldPtr saveGWorld;
1518 GDHandle saveGDevice;
1519 GWorldPtr tempGWorld;
1528 depth = data[0].pixelDepth;
1531 theGDH = data[0].theGDH;
1533 /* Obtain size rectangle */
1534 pictRect = (**pictH).picFrame;
1535 OffsetRect(&pictRect, -pictRect.left, -pictRect.top);
1537 /* Create a GWorld */
1538 err = NewGWorld(&tempGWorld, depth, &pictRect, nil,
1539 theGDH, noNewDevice);
1548 *pictGWorld = tempGWorld;
1551 GetGWorld(&saveGWorld, &saveGDevice);
1554 SetGWorld(tempGWorld, nil);
1556 /* Dump the pict into the GWorld */
1557 (void)LockPixels(GetGWorldPixMap(tempGWorld));
1558 EraseRect(&pictRect);
1559 DrawPicture(pictH, &pictRect);
1560 UnlockPixels(GetGWorldPixMap(tempGWorld));
1562 /* Restore GWorld */
1563 SetGWorld(saveGWorld, saveGDevice);
1569 #endif /* MACH_O_CARBON */
1573 * Init the global "frameP"
1576 static errr globe_init(void)
1580 GWorldPtr tempPictGWorldP;
1582 #ifdef MACH_O_CARBON
1586 #endif /* MACH_O_CARBON */
1588 /* Use window XXX XXX XXX */
1589 #if TARGET_API_MAC_CARBON
1590 SetPortWindowPort(data[0].w);
1596 #ifdef MACH_O_CARBON
1598 /* Get the tile resources */
1599 if (!get_resource_spec(pictID, CFSTR("png"), &pict_spec)) return (-1);
1602 err = create_gworld_from_spec(&tempPictGWorldP, &pict_spec);
1605 if (err != noErr) return (err);
1607 /* Create the frame */
1608 frameP = (FrameRec*)NewPtrClear((Size)sizeof(FrameRec));
1610 /* Analyze result */
1613 /* Dispose of image GWorld */
1614 DisposeGWorld(tempPictGWorldP);
1616 /* Fake error code */
1621 frameP->framePort = tempPictGWorldP;
1624 BenSWLockFrame(frameP);
1626 #else /* MACH_O_CARBON */
1628 /* Get the pict resource */
1629 newPictH = GetPicture(pictID);
1631 /* Analyze result */
1632 err = (newPictH ? 0 : -1);
1639 err = BenSWCreateGWorldFromPict(&tempPictGWorldP, newPictH);
1641 /* Release resource */
1642 ReleaseResource((Handle)newPictH);
1647 /* Create the frame */
1648 frameP = (FrameRec*)NewPtrClear((Size)sizeof(FrameRec));
1650 /* Analyze result */
1651 err = (frameP ? 0 : -1);
1657 frameP->framePort = tempPictGWorldP;
1660 BenSWLockFrame(frameP);
1664 #endif /* MACH_O_CARBON */
1673 * Nuke the global "frameP"
1675 static errr globe_nuke(void)
1681 BenSWUnlockFrame(frameP);
1683 /* Dispose of the GWorld */
1684 DisposeGWorld(frameP->framePort);
1686 /* Dispose of the memory */
1687 DisposePtr((Ptr)frameP);
1694 FlushEvents(everyEvent, 0);
1701 # ifdef USE_ASYNC_SOUND
1704 * Asynchronous sound player revised
1706 #if defined(USE_QT_SOUND) && !defined(MACH_O_CARBON)
1707 # undef USE_QT_SOUND
1708 #endif /* USE_QT_SOUND && !MACH_O_CARBON */
1712 * Number of channels in the channel pool
1714 #if TARGET_API_MAC_CARBON
1715 #define MAX_CHANNELS 8
1717 #define MAX_CHANNELS 4
1721 * A pool of sound channels
1723 static SndChannelPtr channels[MAX_CHANNELS];
1726 * Status of the channel pool
1728 static Boolean channel_initialised = FALSE;
1731 * Data handles containing sound samples
1733 static SndListHandle samples[SOUND_MAX];
1736 * Reference counts of sound samples
1738 static SInt16 sample_refs[SOUND_MAX];
1744 * These constants aren't used by the program at the moment.
1746 #define SOUND_VOLUME_MIN 0 /* Default minimum sound volume */
1747 #define SOUND_VOLUME_MAX 255 /* Default maximum sound volume */
1748 #define VOLUME_MIN 0 /* Minimum sound volume in % */
1749 #define VOLUME_MAX 100 /* Maximum sound volume in % */
1750 #define VOLUME_INC 5 /* Increment sound volume in % */
1752 /* I'm just too lazy to write a panel for this XXX XXX */
1753 static SInt16 sound_volume = SOUND_VOLUME_MAX;
1758 * QuickTime sound, by Ron Anderson
1760 * I didn't choose to use Windows-style .ini files (Ron wrote a parser
1761 * for it, but...), nor did I use lib/xtra directory, hoping someone
1762 * would code plist-based configuration code in the future -- pelpel
1767 * Load sound effects from data-fork resources. They are wav files
1768 * with the same names as angband_sound_name[] (variable.c)
1770 * Globals referenced: angband_sound_name[]
1771 * Globals updated: samples[] (they can be *huge*)
1773 static void load_sounds(void)
1778 /* Start QuickTime */
1779 err = EnterMovies();
1782 if (err != noErr) return;
1785 * This loop may take a while depending on the count and size of samples
1788 * We should use a progress dialog for this.
1790 for (i = 1; i < SOUND_MAX; i++)
1792 /* Apple APIs always give me headacke :( */
1803 /* Allocate CFString with the name of sound event to be processed */
1804 name = CFStringCreateWithCString(NULL, angband_sound_name[i],
1805 kTextEncodingUS_ASCII);
1808 if (name == NULL) continue;
1810 /* Find sound sample resource with the same name */
1811 res = get_resource_spec(name, CFSTR("wav"), &spec);
1813 /* Free the reference to CFString */
1819 /* Open the sound file */
1820 err = OpenMovieFile(&spec, &file_id, fsRdPerm);
1823 if (err != noErr) continue;
1825 /* Create Movie from the file */
1826 err = NewMovieFromFile(&movie, file_id, &res_id, movie_name,
1827 newMovieActive, NULL);
1830 if (err != noErr) goto close_file;
1832 /* Get the first track of the movie */
1833 track = GetMovieIndTrackType(movie, 1, AudioMediaCharacteristic,
1834 movieTrackCharacteristic | movieTrackEnabledOnly );
1837 if (track == NULL) goto close_movie;
1839 /* Allocate a handle to store sample */
1843 if (h == NULL) goto close_track;
1845 /* Dump the sample into the handle */
1846 err = PutMovieIntoTypedHandle(movie, track, soundListRsrc, h, 0,
1847 GetTrackDuration(track), 0L, NULL);
1852 /* Store the handle in the sample list */
1853 samples[i] = (SndListHandle)h;
1859 /* Free unused handle */
1863 /* Free the track */
1864 close_track: DisposeMovieTrack(track);
1866 /* Free the movie */
1867 close_movie: DisposeMovie(movie);
1869 /* Close the movie file */
1870 close_file: CloseMovieFile(file_id);
1873 /* Stop QuickTime */
1877 #else /* USE_QT_SOUND */
1880 * Return a handle of 'snd ' resource given Angband sound event number,
1881 * or NULL if it isn't found.
1883 * Globals referenced: angband_sound_name[] (variable.c)
1885 static SndListHandle find_sound(int num)
1889 /* Get the proper sound name */
1890 strnfmt((char*)sound + 1, 255, "%.16s.wav", angband_sound_name[num]);
1891 sound[0] = strlen((char*)sound + 1);
1893 /* Obtain resource XXX XXX XXX */
1894 return ((SndListHandle)GetNamedResource('snd ', sound));
1897 #endif /* USE_QT_SOUND */
1901 * Clean up sound support - to be called when the game exits.
1903 * Globals referenced: channels[], samples[], sample_refs[].
1905 static void cleanup_sound(void)
1909 /* No need to clean it up */
1910 if (!channel_initialised) return;
1912 /* Dispose channels */
1913 for (i = 0; i < MAX_CHANNELS; i++)
1915 /* Drain sound commands and free the channel */
1916 SndDisposeChannel(channels[i], TRUE);
1919 /* Free sound data */
1920 for (i = 1; i < SOUND_MAX; i++)
1923 if ((sample_refs[i] > 0) && (samples[i] != NULL))
1926 HUnlock((Handle)samples[i]);
1929 #ifndef USE_QT_SOUND
1932 if (samples[i]) ReleaseResource((Handle)samples[i]);
1936 if (samples[i]) DisposeHandle((Handle)samples[i]);
1937 #endif /* !USE_QT_SOUND */
1943 * Play sound effects asynchronously -- pelpel
1945 * I don't believe those who first started using the previous implementations
1946 * imagined this is *much* more complicated as it may seem. Anyway,
1947 * introduced round-robin scheduling of channels and made it much more
1948 * paranoid about HLock/HUnlock.
1950 * XXX XXX de-refcounting, HUnlock and ReleaseResource should be done
1951 * using channel's callback procedures, which set global flags, and
1952 * a procedure hooked into CheckEvents does housekeeping. On the other
1953 * hand, this lazy reclaiming strategy keeps things simple (no interrupt
1954 * time code) and provides a sort of cache for sound data.
1956 * Globals referenced: channel_initialised, channels[], samples[],
1958 * Globals updated: ditto.
1960 static void play_sound(int num, SInt16 vol)
1969 static int next_chan;
1970 static SInt16 channel_occupants[MAX_CHANNELS];
1971 static SndCommand volume_cmd, quiet_cmd;
1974 /* Initialise sound channels */
1975 if (!channel_initialised)
1977 for (i = 0; i < MAX_CHANNELS; i++)
1979 /* Paranoia - Clear occupant table */
1980 /* channel_occupants[i] = 0; */
1982 /* Create sound channel for all sounds to play from */
1983 err = SndNewChannel(&channels[i], sampledSynth, initMono, 0L);
1991 SndDisposeChannel(channels[i], TRUE);
1996 plog("¥µ¥¦¥ó¥É¥Á¥ã¥ó¥Í¥ë¤ò½é´ü²½½ÐÍè¤Þ¤»¤ó!");
1998 plog("Cannot initialise sound channels!");
2001 /* Cancel request */
2002 use_sound = arg_sound = FALSE;
2009 /* First channel to use */
2012 /* Prepare volume command */
2013 volume_cmd.cmd = volumeCmd;
2014 volume_cmd.param1 = 0;
2015 volume_cmd.param2 = 0;
2017 /* Prepare quiet command */
2018 quiet_cmd.cmd = quietCmd;
2019 quiet_cmd.param1 = 0;
2020 quiet_cmd.param2 = 0;
2022 /* Initialisation complete */
2023 channel_initialised = TRUE;
2027 if ((num <= 0) || (num >= SOUND_MAX)) return;
2029 /* Prepare volume command */
2030 volume_cmd.param2 = ((SInt32)vol << 16) | vol;
2032 /* Channel to use (round robin) */
2033 chan = channels[next_chan];
2035 /* See if the resource is already in use */
2036 if (sample_refs[num] > 0)
2038 /* Resource in use */
2041 /* Increase the refcount */
2045 /* Sound is not currently in use */
2048 /* Get handle for the sound */
2052 h = find_sound(num);
2053 #endif /* USE_QT_SOUND */
2055 /* Sample not available */
2056 if (h == NULL) return;
2058 #ifndef USE_QT_SOUND
2061 LoadResource((Handle)h);
2066 #endif /* !USE_QT_SOUND */
2068 /* Lock the handle */
2071 /* Initialise refcount */
2072 sample_refs[num] = 1;
2075 /* Poll the channel */
2076 err = SndChannelStatus(chan, sizeof(SCStatus), &status);
2078 /* It isn't available */
2079 if ((err != noErr) || status.scChannelBusy)
2082 SndDoImmediate(chan, &quiet_cmd);
2085 /* Previously played sound on this channel */
2086 prev_num = channel_occupants[next_chan];
2088 /* Process previously played sound */
2091 /* Decrease refcount */
2092 sample_refs[prev_num]--;
2094 /* We can free it now */
2095 if (sample_refs[prev_num] <= 0)
2098 HUnlock((Handle)samples[prev_num]);
2100 #ifndef USE_QT_SOUND
2103 ReleaseResource((Handle)samples[prev_num]);
2106 samples[prev_num] = NULL;
2108 #endif /* !USE_QT_SOUND */
2111 sample_refs[prev_num] = 0;
2115 /* Remember this sound as the current occupant of the channel */
2116 channel_occupants[next_chan] = num;
2118 /* Set up volume for channel */
2119 SndDoImmediate(chan, &volume_cmd);
2121 /* Play new sound asynchronously */
2122 SndPlay(chan, h, TRUE);
2124 /* Schedule next channel (round robin) */
2126 if (next_chan >= MAX_CHANNELS) next_chan = 0;
2129 # else /* USE_ASYNC_SOUND */
2132 * Play sound synchronously
2134 * This may not be your choice, but much safer and much less resource hungry.
2136 static void play_sound(int num, SInt16 vol)
2141 /* Get the proper sound name */
2142 strnfmt((char*)sound + 1, 255, "%.16s.wav", angband_sound_name[num]);
2143 sound[0] = strlen((char*)sound + 1);
2145 /* Obtain resource XXX XXX XXX */
2146 handle = GetNamedResource('snd ', sound);
2149 if (handle == NULL) return;
2152 LoadResource(handle);
2155 /* Play sound (wait for completion) */
2156 SndPlay(NULL, (SndListHandle)handle, FALSE);
2158 /* Unlock and release */
2160 ReleaseResource(handle);
2163 # endif /* USE_ASYNC_SOUND */
2170 static short soundmode[8];
2173 #define SND_ATTACK 1
2178 #define SND_CMD_ERROR 6
2180 #ifndef MACH_O_CARBON
2182 static int soundchoice[] = {
2250 static int ext_sound = 0;
2251 static int ext_graf = 0;
2253 #endif /* !MACH_O_CARBON */
2255 #endif /* ANGBAND_LITE_MAC */
2259 /*** Support for the "z-term.c" package ***/
2263 * Initialize a new Term
2265 * Note also the "window type" called "noGrowDocProc", which might be more
2266 * appropriate for the main "screen" window.
2268 * Note the use of "srcCopy" mode for optimized screen writes.
2270 static void Term_init_mac(term *t)
2272 term_data *td = (term_data*)(t->data);
2274 static RGBColor black = {0x0000,0x0000,0x0000};
2275 static RGBColor white = {0xFFFF,0xFFFF,0xFFFF};
2277 #ifdef ANGBAND_LITE_MAC
2279 /* Make the window */
2280 td->w = NewWindow(0, &td->r, td->title, 0, noGrowDocProc, (WindowPtr)-1, 1, 0L);
2282 #else /* ANGBAND_LITE_MAC */
2284 /* Make the window */
2285 td->w = NewCWindow(0, &td->r, td->title, 0, documentProc, (WindowPtr)-1, 1, 0L);
2287 #endif /* ANGBAND_LITE_MAC */
2289 /* Activate the window */
2292 /* Erase behind words */
2295 /* Apply and Verify */
2296 term_data_check_font(td);
2297 term_data_check_size(td);
2299 /* Resize the window */
2300 term_data_resize(td);
2302 #ifdef ANGBAND_LITE_MAC
2304 /* Prepare the colors (base colors) */
2305 BackColor(blackColor);
2306 ForeColor(whiteColor);
2308 #else /* ANGBAND_LITE_MAC */
2310 /* Prepare the colors (real colors) */
2311 RGBBackColor(&black);
2312 RGBForeColor(&white);
2318 GDHandle currentGDH;
2319 GWorldPtr windowGWorld;
2320 PixMapHandle basePixMap;
2322 /* Obtain the rect */
2323 #if TARGET_API_MAC_CARBON
2324 GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &globalRect );
2326 globalRect = td->w->portRect;
2327 LocalToGlobal((Point*)&globalRect.top);
2328 LocalToGlobal((Point*)&globalRect.bottom);
2331 /* Obtain the proper GDH */
2332 mainGDH = GetMaxDevice(&globalRect);
2334 /* Extract GWorld and GDH */
2335 GetGWorld(&windowGWorld, ¤tGDH);
2337 /* Obtain base pixmap */
2338 basePixMap = (**mainGDH).gdPMap;
2340 /* Save pixel depth */
2341 td->pixelDepth = (**basePixMap).pixelSize;
2343 /* Save Window GWorld */
2344 td->theGWorld = windowGWorld;
2346 /* Save Window GDH */
2347 td->theGDH = currentGDH;
2350 td->mainSWGDH = mainGDH;
2353 #endif /* ANGBAND_LITE_MAC */
2358 #if TARGET_API_MAC_CARBON
2359 GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &portRect );
2360 global_to_local( &portRect );
2362 portRect = td->w->portRect;
2364 /* Clip to the window */
2365 ClipRect(&portRect);
2367 /* Erase the window */
2368 EraseRect(&portRect);
2370 /* Invalidate the window */
2371 #if TARGET_API_MAC_CARBON
2372 InvalWindowRect((WindowRef)(td->w), (const Rect *)(&portRect));
2374 InvalRect(&portRect);
2377 /* Display the window if needed */
2378 if (td->mapped) ShowWindow(td->w);
2380 /* Hack -- set "mapped" flag */
2381 t->mapped_flag = td->mapped;
2387 /* if (err == noErr)
2398 static void Term_nuke_mac(term *t)
2411 static errr Term_user_mac(int n)
2425 static errr Term_xtra_mac_react(void)
2427 term_data *td = (term_data*)(Term->data);
2433 #ifdef ANGBAND_LITE_MAC
2437 #else /* ANGBAND_LITE_MAC */
2440 if (use_sound != arg_sound)
2443 use_sound = arg_sound;
2447 /* Handle graphics */
2448 if (graf_mode_req != graf_mode)
2450 /* dispose old GWorld's if present */
2453 /* Setup parameters according to request */
2454 switch (graf_mode_req)
2456 /* ASCII - no graphics whatsoever */
2457 case GRAF_MODE_NONE:
2459 use_graphics = arg_graphics = GRAPHICS_NONE;
2464 * 8x8 tiles (PICT id 1001)
2465 * no transparency effect
2466 * "old" graphics definitions
2470 use_graphics = arg_graphics = GRAPHICS_ORIGINAL;
2471 ANGBAND_GRAF = "old";
2472 #ifdef MACH_O_CARBON
2473 pictID = CFSTR("8x8");
2476 #endif /* MACH_O_CARBON */
2477 grafWidth = grafHeight = 8;
2482 * 16x16 tiles (images: PICT id 1002)
2483 * with transparency effect
2484 * "new" graphics definitions
2486 case GRAF_MODE_16X16:
2488 use_graphics = arg_graphics = GRAPHICS_ADAM_BOLT;
2489 ANGBAND_GRAF = "new";
2490 #ifdef MACH_O_CARBON
2491 pictID = CFSTR("16x16");
2494 #endif /* MACH_O_CARBON */
2495 grafWidth = grafHeight = 16;
2500 if ((graf_mode_req != GRAF_MODE_NONE) && !frameP && (globe_init() != 0))
2503 plog("¥°¥é¥Õ¥£¥Ã¥¯¤Î½é´ü²½¤Ï½ÐÍè¤Þ¤»¤ó¤Ç¤·¤¿.");
2505 plog("Cannot initialize graphics!");
2508 /* reject request */
2509 graf_mode_req = GRAF_MODE_NONE;
2511 /* reset graphics flags */
2512 use_graphics = arg_graphics = FALSE;
2516 /* update current graphics mode */
2517 graf_mode = graf_mode_req;
2519 /* Apply and Verify */
2520 term_data_check_size(td);
2522 /* Resize the window */
2523 term_data_resize(td);
2529 #endif /* ANGBAND_LITE_MAC */
2537 * Do a "special thing"
2539 static errr Term_xtra_mac(int n, int v)
2541 term_data *td = (term_data*)(Term->data);
2549 case TERM_XTRA_NOISE:
2558 #ifdef ANGBAND_LITE_MAC
2562 #else /* ANGBAND_LITE_MAC */
2565 case TERM_XTRA_SOUND:
2568 play_sound(v, sound_volume);
2574 #endif /* ANGBAND_LITE_MAC */
2576 /* Process random events */
2577 case TERM_XTRA_BORED:
2579 /* Process an event */
2580 (void)CheckEvents(FALSE);
2586 /* Process pending events */
2587 case TERM_XTRA_EVENT:
2589 /* Process an event */
2590 (void)CheckEvents(v);
2596 /* Flush all pending events (if any) */
2597 case TERM_XTRA_FLUSH:
2599 /* Hack -- flush all events */
2600 while (CheckEvents(TRUE)) /* loop */;
2606 /* Hack -- Change the "soft level" */
2607 case TERM_XTRA_LEVEL:
2609 /* Activate if requested */
2610 if (v) activate(td->w);
2616 /* Clear the screen */
2617 case TERM_XTRA_CLEAR:
2621 #if TARGET_API_MAC_CARBON
2622 GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &portRect );
2623 global_to_local( &portRect );
2625 portRect = td->w->portRect;
2628 /* No clipping XXX XXX XXX */
2629 ClipRect(&portRect);
2631 /* Erase the window */
2632 EraseRect(&portRect);
2635 term_data_color(td, TERM_WHITE);
2637 /* Frame the window in white */
2639 LineTo(0, td->size_hgt-1);
2640 LineTo(td->size_wid-1, td->size_hgt-1);
2641 LineTo(td->size_wid-1, 0);
2643 /* Clip to the new size */
2644 r.left = portRect.left + td->size_ow1;
2645 r.top = portRect.top + td->size_oh1;
2646 r.right = portRect.right - td->size_ow2;
2647 r.bottom = portRect.bottom - td->size_oh2;
2654 /* React to changes */
2655 case TERM_XTRA_REACT:
2657 /* React to changes */
2658 return (Term_xtra_mac_react());
2661 /* Delay (milliseconds) */
2662 case TERM_XTRA_DELAY:
2667 #if TARGET_API_MAC_CARBON
2671 /* Convert millisecs to ticks */
2672 ticks = (v * 60L) / 1000;
2675 * Hack? - Put the programme into sleep.
2676 * No events match ~everyEvent, so nothing
2677 * should be lost in Angband's event queue.
2678 * Even if ticks are 0, it's worth calling for
2679 * the above mentioned reasons.
2681 WaitNextEvent((EventMask)~everyEvent, &tmp, ticks, nil);
2683 long m = TickCount() + (v * 60L) / 1000;
2686 while (TickCount() < m) /* loop */;
2702 * Low level graphics (Assumes valid input).
2703 * Draw a "cursor" at (x,y), using a "yellow box".
2704 * We are allowed to use "Term_grab()" to determine
2705 * the current screen contents (for inverting, etc).
2707 static errr Term_curs_mac(int x, int y)
2711 term_data *td = (term_data*)(Term->data);
2714 term_data_color(td, TERM_YELLOW);
2716 /* Frame the grid */
2717 r.left = x * td->tile_wid + td->size_ow1;
2718 r.right = r.left + td->tile_wid;
2719 r.top = y * td->tile_hgt + td->size_oh1;
2720 r.bottom = r.top + td->tile_hgt;
2730 * Low level graphics (Assumes valid input).
2731 * Draw a "big cursor" at (x,y), using a "yellow box".
2732 * We are allowed to use "Term_grab()" to determine
2733 * the current screen contents (for inverting, etc).
2735 static errr Term_bigcurs_mac(int x, int y)
2739 term_data *td = (term_data*)(Term->data);
2742 term_data_color(td, TERM_YELLOW);
2744 /* Frame the grid */
2745 r.left = x * td->tile_wid + td->size_ow1;
2746 r.right = r.left + 2 * td->tile_wid;
2747 r.top = y * td->tile_hgt + td->size_oh1;
2748 r.bottom = r.top + td->tile_hgt;
2758 * Low level graphics (Assumes valid input)
2760 * Erase "n" characters starting at (x,y)
2762 static errr Term_wipe_mac(int x, int y, int n)
2766 term_data *td = (term_data*)(Term->data);
2768 /* Erase the block of characters */
2769 r.left = x * td->tile_wid + td->size_ow1;
2770 r.right = r.left + n * td->tile_wid;
2771 r.top = y * td->tile_hgt + td->size_oh1;
2772 r.bottom = r.top + td->tile_hgt;
2781 * Low level graphics. Assumes valid input.
2783 * Draw several ("n") chars, with an attr, at a given location.
2785 static errr Term_text_mac(int x, int y, int n, byte a, const char *cp)
2789 term_data *td = (term_data*)(Term->data);
2792 term_data_color(td, (a & 0x0F));
2794 /* Starting pixel */
2795 xp = x * td->tile_wid + td->tile_o_x + td->size_ow1;
2796 yp = y * td->tile_hgt + td->tile_o_y + td->size_oh1;
2798 /* Move to the correct location */
2801 /* Draw the character */
2802 if (n == 1) DrawChar(*cp);
2804 /* Draw the string */
2805 else DrawText(cp, 0, n);
2813 * Low level graphics (Assumes valid input)
2815 * Erase "n" characters starting at (x,y)
2817 static errr Term_pict_mac(int x, int y, int n, const byte *ap, const char *cp,
2818 const byte *tap, const char *tcp)
2822 term_data *td = (term_data*)(Term->data);
2823 GDHandle saveGDevice;
2824 GWorldPtr saveGWorld;
2827 GetGWorld(&saveGWorld, &saveGDevice);
2829 r2.left = x * td->tile_wid + td->size_ow1;
2830 r2.right = r2.left + td->tile_wid;
2831 r2.top = y * td->tile_hgt + td->size_oh1;
2832 r2.bottom = r2.top + td->tile_hgt;
2836 /* Instantiate font */
2837 TextFont(td->font_id);
2838 TextSize(td->font_size);
2839 TextFace(td->font_face);
2841 /* Restore colors */
2842 BackColor(blackColor);
2843 ForeColor(whiteColor);
2847 /* Destination rectangle */
2848 /* r2.left = x * td->tile_wid + td->size_ow1;
2849 r2.top = y * td->tile_hgt + td->size_oh1;
2850 r2.bottom = r2.top + td->tile_hgt;*/
2854 /* Scan the input */
2855 for (i = 0; i < n; i++)
2862 /* Second byte of bigtile */
2863 if (use_bigtile && a == 255)
2866 r2.left += td->tile_wid;
2871 /* Prepare right of rectangle now */
2872 r2.right = r2.left + td->tile_wid;
2874 #ifdef ANGBAND_LITE_MAC
2878 #else /* ANGBAND_LITE_MAC */
2880 /* Graphics -- if Available and Needed */
2881 if (use_graphics && ((byte)a & 0x80) && ((byte)c & 0x80))
2883 #if TARGET_API_MAC_CARBON
2884 PixMapHandle srcBitMap = GetGWorldPixMap(frameP->framePort);
2885 PixMapHandle destBitMap;
2887 BitMapPtr srcBitMap = (BitMapPtr)(frameP->framePix);
2888 BitMapPtr destBitMap;
2895 bool terrain_flag = FALSE;
2899 if ((a != ta || c != tc) &&
2900 ((byte)ta & 0x80) && ((byte)tc & 0x80))
2903 row = ((byte)ta & 0x7F);
2904 col = ((byte)tc & 0x7F);
2906 /* Terrain Source rectangle */
2907 terrain_r.left = col * grafWidth;
2908 terrain_r.top = row * grafHeight;
2909 terrain_r.right = terrain_r.left + grafWidth;
2910 terrain_r.bottom = terrain_r.top + grafHeight;
2912 terrain_flag = TRUE;
2916 row = ((byte)a & 0x7F);
2917 col = ((byte)c & 0x7F);
2919 /* Source rectangle */
2920 r1.left = col * grafWidth;
2921 r1.top = row * grafHeight;
2922 r1.right = r1.left + grafWidth;
2923 r1.bottom = r1.top + grafHeight;
2925 /* Hardwire CopyBits */
2926 BackColor(whiteColor);
2927 ForeColor(blackColor);
2929 /* Draw the picture */
2930 #if TARGET_API_MAC_CARBON
2931 destBitMap = GetPortPixMap(GetWindowPort( td->w ));
2933 destBitMap = (BitMapPtr)&(td->w->portBits);
2935 if (use_bigtile) r2.right += td->tile_wid;
2940 * Source mode const = srcCopy:
2942 * determine how close the color of the source
2943 * pixel is to black, and assign this relative
2944 * amount of foreground color to the
2945 * destination pixel; determine how close the
2946 * color of the source pixel is to white, and
2947 * assign this relative amount of background
2948 * color to the destination pixel
2950 #if TARGET_API_MAC_CARBON
2951 CopyBits( (BitMap *) *srcBitMap, (BitMap *) *destBitMap, &terrain_r, &r2, srcCopy, NULL);
2953 CopyBits( srcBitMap, destBitMap, &terrain_r, &r2, srcCopy, NULL );
2956 * Draw transparent tile
2957 * BackColor is ignored and the destination is
2960 BackColor(blackColor);
2961 #if TARGET_API_MAC_CARBON
2962 CopyBits( (BitMap *) *srcBitMap, (BitMap *) *destBitMap, &r1, &r2, transparent, NULL);
2964 CopyBits( srcBitMap, destBitMap, &r1, &r2, transparent, NULL );
2969 #if TARGET_API_MAC_CARBON
2970 CopyBits( (BitMap *) *srcBitMap, (BitMap *) *destBitMap, &r1, &r2, srcCopy, NULL);
2972 CopyBits( srcBitMap, destBitMap, &r1, &r2, srcCopy, NULL );
2976 /* Restore colors */
2977 BackColor(blackColor);
2978 ForeColor(whiteColor);
2987 #endif /* ANGBAND_LITE_MAC */
2995 term_data_color(td, (a & 0x0F));
2997 /* Starting pixel */
2998 xp = r2.left + td->tile_o_x;
2999 yp = r2.top + td->tile_o_y;
3001 /* Move to the correct location */
3007 /* Double width rectangle */
3008 r2.right += td->tile_wid;
3013 /* Draw the character */
3018 r2.left += td->tile_wid;
3026 /* Draw the character */
3032 r2.left += td->tile_wid;
3041 * Create and initialize window number "i"
3043 static void term_data_link(int i)
3047 term_data *td = &data[i];
3052 /* Require mapped */
3053 if (!td->mapped) return;
3058 /* Initialize the term */
3059 term_init(td->t, td->cols, td->rows, td->keys);
3061 /* Use a "software" cursor */
3062 td->t->soft_cursor = TRUE;
3064 /* Erase with "white space" */
3065 td->t->attr_blank = TERM_WHITE;
3066 td->t->char_blank = ' ';
3068 /* Prepare the init/nuke hooks */
3069 td->t->init_hook = Term_init_mac;
3070 td->t->nuke_hook = Term_nuke_mac;
3072 /* Prepare the function hooks */
3073 td->t->user_hook = Term_user_mac;
3074 td->t->xtra_hook = Term_xtra_mac;
3075 td->t->wipe_hook = Term_wipe_mac;
3076 td->t->curs_hook = Term_curs_mac;
3077 td->t->bigcurs_hook = Term_bigcurs_mac;
3078 td->t->text_hook = Term_text_mac;
3079 td->t->pict_hook = Term_pict_mac;
3081 /* Link the local structure */
3082 td->t->data = (vptr)(td);
3085 Term_activate(td->t);
3087 /* Global pointer */
3088 angband_term[i] = td->t;
3096 #ifdef MACH_O_CARBON
3100 * Return a POSIX pathname of the lib directory, or NULL if it can't be
3101 * located. Caller must supply a buffer along with its size in bytes,
3102 * where returned pathname will be stored.
3103 * I prefer use of goto's to several nested if's, if they involve error
3104 * handling. Sorry if you are offended by their presence. Modern
3105 * languages have neater constructs for this kind of jobs -- pelpel
3107 static char *locate_lib(char *buf, size_t size)
3109 CFURLRef main_url = NULL;
3110 CFStringRef main_str = NULL;
3114 /* Obtain the URL of the main bundle */
3115 main_url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
3118 if (main_url == NULL) goto ret;
3120 /* Convert it to POSIX pathname */
3121 main_str = CFURLCopyFileSystemPath(main_url, kCFURLPOSIXPathStyle);
3124 if (main_str == NULL) goto ret;
3126 /* Convert it again from darn unisomething encoding to ASCII */
3127 if (CFStringGetCString(main_str, buf, size, kTextEncodingUS_ASCII) == FALSE)
3130 /* Find the last '/' in the pathname */
3131 p = strrchr(buf, '/');
3133 /* Paranoia - cannot happen */
3134 if (p == NULL) goto ret;
3136 /* Remove the trailing path */
3140 * Paranoia - bounds check, with 5 being the length of "/lib/"
3141 * and 1 for terminating '\0'.
3143 if (strlen(buf) + 5 + 1 > size) goto ret;
3145 /* Append "/lib/" */
3146 strcat(buf, "/lib/");
3153 /* Release objects allocated and implicitly retained by the program */
3154 if (main_str) CFRelease(main_str);
3155 if (main_url) CFRelease(main_url);
3157 /* pathname of the lib folder or NULL */
3162 #else /* MACH_O_CARBON */
3166 * Set the "current working directory" (also known as the "default"
3167 * volume/directory) to the location of the current application.
3169 * Code by: Maarten Hazewinkel (mmhazewi@cs.ruu.nl)
3171 * This function does not appear to work correctly with System 6.
3173 static void SetupAppDir(void)
3177 char errString[100];
3179 /* Get the location of the Angband executable */
3180 fcbBlock.ioCompletion = NULL;
3181 fcbBlock.ioNamePtr = NULL;
3182 fcbBlock.ioVRefNum = 0;
3183 fcbBlock.ioRefNum = CurResFile();
3184 fcbBlock.ioFCBIndx = 0;
3185 err = PBGetFCBInfo(&fcbBlock, FALSE);
3189 sprintf(errString, "PBGetFCBInfo ¥¨¥é¡¼ #%d.\r ½ªÎ»¤·¤Þ¤¹.", err);
3191 sprintf(errString, "Fatal PBGetFCBInfo Error #%d.\r Exiting.", err);
3193 mac_warning(errString);
3197 /* Extract the Vol and Dir */
3198 app_vol = fcbBlock.ioFCBVRefNum;
3199 app_dir = fcbBlock.ioFCBParID;
3201 /* Set the current working directory to that location */
3202 err = HSetVol(NULL, app_vol, app_dir);
3206 sprintf(errString, "HSetVol ¥¨¥é¡¼ #%d.\r ½ªÎ»¤·¤Þ¤¹.", err);
3208 sprintf(errString, "Fatal HSetVol Error #%d.\r Exiting.", err);
3210 mac_warning(errString);
3219 #if TARGET_API_MAC_CARBON
3221 * Using Core Foundation's Preferences services -- pelpel
3223 * Requires OS 8.6 or greater with CarbonLib 1.1 or greater. Or OS X,
3226 * Without this, we can support older versions of OS 8 as well
3227 * (with CarbonLib 1.0.4).
3229 * Frequent allocation/deallocation of small chunks of data is
3230 * far from my liking, but since this is only called at the
3231 * beginning and the end of a session, I hope this hardly matters.
3236 * Store "value" as the value for preferences item name
3239 static void save_pref_short(const char *key, short value)
3242 CFNumberRef cf_value;
3244 /* allocate and initialise the key */
3245 cf_key = CFStringCreateWithCString(NULL, key, kTextEncodingUS_ASCII);
3247 /* allocate and initialise the value */
3248 cf_value = CFNumberCreate(NULL, kCFNumberShortType, &value);
3250 if ((cf_key != NULL) && (cf_value != NULL))
3252 /* Store the key-value pair in the applications preferences */
3253 CFPreferencesSetAppValue(
3256 kCFPreferencesCurrentApplication);
3260 * Free CF data - the reverse order is a vain attempt to
3261 * minimise memory fragmentation.
3263 if (cf_value) CFRelease(cf_value);
3264 if (cf_key) CFRelease(cf_key);
3269 * Load preference value for key, returns TRUE if it succeeds with
3270 * vptr updated appropriately, FALSE otherwise.
3272 static bool query_load_pref_short(const char *key, short *vptr)
3275 CFNumberRef cf_value;
3277 /* allocate and initialise the key */
3278 cf_key = CFStringCreateWithCString(NULL, key, kTextEncodingUS_ASCII);
3281 if (cf_key == NULL) return (FALSE);
3283 /* Retrieve value for the key */
3284 cf_value = CFPreferencesCopyAppValue(
3286 kCFPreferencesCurrentApplication);
3288 /* Value not found */
3289 if (cf_value == NULL)
3295 /* Convert the value to short */
3302 CFRelease(cf_value);
3311 * Update short data pointed by vptr only if preferences
3312 * value for key is located.
3314 static void load_pref_short(const char *key, short *vptr)
3318 if (query_load_pref_short(key, &tmp)) *vptr = tmp;
3324 * Save preferences to preferences file for current host+current user+
3325 * current application.
3327 static void cf_save_prefs()
3332 save_pref_short("version.major", FAKE_VERSION);
3333 save_pref_short("version.minor", FAKE_VER_MAJOR);
3334 save_pref_short("version.patch", FAKE_VER_MINOR);
3335 save_pref_short("version.extra", FAKE_VER_PATCH);
3338 save_pref_short("arg.arg_sound", arg_sound);
3339 save_pref_short("arg.graf_mode", graf_mode);
3340 save_pref_short("arg.arg_bigtile", arg_bigtile);
3342 #ifndef MACH_O_CARBON
3344 for( i = 0 ; i < 7 ; i++ )
3345 save_pref_short(format("sound%d.on", i), soundmode[i]);
3346 #endif /* MACH_O_CARBON */
3349 for (i = 0; i < MAX_TERM_DATA; i++)
3351 term_data *td = &data[i];
3353 save_pref_short(format("term%d.mapped", i), td->mapped);
3355 save_pref_short(format("term%d.font_id", i), td->font_id);
3356 save_pref_short(format("term%d.font_size", i), td->font_size);
3357 save_pref_short(format("term%d.font_face", i), td->font_face);
3359 save_pref_short(format("term%d.tile_wid", i), td->tile_wid);
3360 save_pref_short(format("term%d.tile_hgt", i), td->tile_hgt);
3362 save_pref_short(format("term%d.cols", i), td->cols);
3363 save_pref_short(format("term%d.rows", i), td->rows);
3364 save_pref_short(format("term%d.left", i), td->r.left);
3365 save_pref_short(format("term%d.top", i), td->r.top);
3369 * Make sure preferences are persistent
3371 CFPreferencesAppSynchronize(
3372 kCFPreferencesCurrentApplication);
3377 * Load preferences from preferences file for current host+current user+
3378 * current application.
3380 static void cf_load_prefs()
3383 short pref_major, pref_minor, pref_patch, pref_extra;
3386 /* Assume nothing is wrong, yet */
3389 /* Load version information */
3390 ok &= query_load_pref_short("version.major", &pref_major);
3391 ok &= query_load_pref_short("version.minor", &pref_minor);
3392 ok &= query_load_pref_short("version.patch", &pref_patch);
3393 ok &= query_load_pref_short("version.extra", &pref_extra);
3395 /* Any of the above failed */
3398 /* This may be the first run */
3400 mac_warning("½é´üÀßÄê¥Õ¥¡¥¤¥ë¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó¡£");
3402 mac_warning("Preferences are not found.");
3405 /* Ignore the rest */
3414 if (query_load_pref_short("arg.arg_sound", &pref_tmp))
3415 arg_sound = pref_tmp;
3418 if (query_load_pref_short("arg.graf_mode", &pref_tmp))
3419 graf_mode_req = pref_tmp;
3421 /* double-width tiles */
3422 if (query_load_pref_short("arg.arg_bigtile", &pref_tmp))
3424 arg_bigtile = use_bigtile = pref_tmp;
3429 #ifndef MACH_O_CARBON
3431 for( i = 0 ; i < 7 ; i++ )
3433 query_load_pref_short(format("sound%d.on", i), &soundmode[i]);
3435 #endif /* MACH_O_CARBON */
3438 for (i = 0; i < MAX_TERM_DATA; i++)
3440 term_data *td = &data[i];
3442 load_pref_short(format("term%d.mapped", i), &td->mapped);
3444 load_pref_short(format("term%d.font_id", i), &td->font_id);
3445 load_pref_short(format("term%d.font_size", i), &td->font_size);
3446 load_pref_short(format("term%d.font_face", i), &td->font_face);
3448 load_pref_short(format("term%d.tile_wid", i), &td->tile_wid);
3449 load_pref_short(format("term%d.tile_hgt", i), &td->tile_hgt);
3451 load_pref_short(format("term%d.cols", i), &td->cols);
3452 load_pref_short(format("term%d.rows", i), &td->rows);
3453 load_pref_short(format("term%d.left", i), &td->r.left);
3454 load_pref_short(format("term%d.top", i), &td->r.top);
3460 * Global "preference" file pointer
3465 * Read a "short" from the file
3467 static int getshort(void)
3471 if (0 == my_fgets(fff, buf, sizeof(buf))) x = atoi(buf);
3476 * Dump a "short" to the file
3478 static void putshort(int x)
3480 fprintf(fff, "%d\n", x);
3486 * Write the "preference" data to the current "file"
3488 static void save_prefs(void)
3495 /*** The current version ***/
3497 putshort(FAKE_VERSION);
3498 putshort(FAKE_VER_MAJOR);
3499 putshort(FAKE_VER_MINOR);
3500 putshort(FAKE_VER_PATCH);
3502 putshort(arg_sound);
3503 putshort(graf_mode);
3504 putshort(arg_bigtile);
3507 for( i = 0 ; i < 7 ; i++ )
3508 putshort(soundmode[i]);
3511 for (i = 0; i < MAX_TERM_DATA; i++)
3516 putshort(td->mapped);
3518 putshort(td->font_id);
3519 putshort(td->font_size);
3520 putshort(td->font_face);
3522 putshort(td->tile_wid);
3523 putshort(td->tile_hgt);
3528 putshort(td->r.left);
3529 putshort(td->r.top);
3535 * Load the preferences from the current "file"
3537 * XXX XXX XXX Being able to undefine various windows is
3538 * slightly bizarre, and may cause problems.
3540 static void load_prefs(void)
3544 int old_version, old_major, old_minor, old_patch;
3549 /*** Version information ***/
3551 /* Preferences version */
3552 old_version = getshort();
3553 old_major = getshort();
3554 old_minor = getshort();
3555 old_patch = getshort();
3557 /* Hack -- Verify or ignore */
3558 if ((old_version != FAKE_VERSION) ||
3559 (old_major != FAKE_VER_MAJOR) ||
3560 (old_minor != FAKE_VER_MINOR) ||
3561 (old_patch != FAKE_VER_PATCH))
3565 mac_warning("¸Å¤¤½é´üÀßÄê¥Õ¥¡¥¤¥ë¤ò̵»ë¤·¤Þ¤¹.");
3567 mac_warning("Ignoring old preferences.");
3573 arg_sound = getshort();
3574 graf_mode_req = getshort();
3575 arg_bigtile = getshort();
3576 use_bigtile = arg_bigtile;
3579 for( i = 0 ; i < 7 ; i++ )
3580 soundmode[i] = getshort();
3583 for (i = 0; i < MAX_TERM_DATA; i++)
3588 td->mapped = getshort();
3590 td->font_id = getshort();
3591 td->font_size = getshort();
3592 td->font_face = getshort();
3594 td->tile_wid = getshort();
3595 td->tile_hgt = getshort();
3597 td->cols = getshort();
3598 td->rows = getshort();
3600 td->r.left = getshort();
3601 td->r.top = getshort();
3604 if (feof(fff)) break;
3607 #endif /* TARGET_API_MAC_CARBON */
3612 * Hack -- default data for a window
3614 static void term_data_hack(term_data *td)
3618 #if TARGET_API_MAC_CARBON
3620 /* Default to Osaka font (Japanese) */
3621 fid = FMGetFontFamilyFromName( "\pOsaka¡ÝÅùÉý" );
3623 /* Default to Monaco font */
3624 fid = FMGetFontFamilyFromName("\pmonaco");
3628 /* Default to ÅùÉýÌÀÄ« font (Japanese) */
3629 GetFNum( "\pÅùÉýÌÀÄ«", &fid);
3630 SetFScaleDisable( true );
3632 /* Default to Monaco font */
3633 GetFNum("\pmonaco", &fid);
3638 WIPE(td, term_data);
3643 /* Default borders */
3654 /* Default font size */
3657 /* Default font face */
3664 /* Default position */
3674 * Read the preference file, Create the windows.
3676 * We attempt to use "FindFolder()" to track down the preference file,
3677 * but if this fails, for any reason, we will try the "SysEnvirons()"
3678 * method, which may work better with System 6.
3680 static void init_windows(void)
3686 #if !TARGET_API_MAC_CARBON
3694 #endif /* !TARGET_API_MAC_CARBON */
3697 /*** Default values ***/
3699 /* Initialize (backwards) */
3700 for (i = MAX_TERM_DATA - 1; i >= 0; i--)
3713 s = angband_term_name[i];
3718 /* Maximal length */
3721 /* Copy the title */
3722 strncpy((char*)(td->title) + 1, s, n);
3724 /* Save the length */
3727 /* Tile the windows */
3728 td->r.left += (b * 30);
3729 td->r.top += (b * 30);
3736 /*** Load preferences ***/
3738 #if TARGET_API_MAC_CARBON
3741 /* Assume failure */
3744 /* Assume failure */
3757 /* Find the folder */
3758 err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
3764 /* Extract a path name */
3765 PathNameFromDirID(dirID, vref, (StringPtr)foo);
3767 /* Convert the string */
3768 ptocstr((StringPtr)foo);
3770 /* Append the preference file name */
3771 strcat(foo, PREF_FILE_NAME);
3773 /* Open the preference file */
3774 fff = fopen(foo, "r");
3781 #endif /* USE_SFL_CODE */
3787 HGetVol(0, &savev, &saved);
3789 /* Go to the "system" folder */
3790 SysEnvirons(curSysEnvVers, &env);
3791 SetVol(0, env.sysVRefNum);
3794 fff = fopen(PREF_FILE_NAME, "r");
3797 HSetVol(0, savev, saved);
3800 /* Load preferences */
3803 /* Load a real preference file */
3806 /* Close the file */
3809 #endif /* TARGET_API_MAC_CARBON */
3812 /*** Instantiate ***/
3823 /* Link (backwards, for stacking order) */
3824 for (i = MAX_TERM_DATA - 1; i >= 0; i--)
3833 Term_activate(td->t);
3836 #ifndef MACH_O_CARBON
3838 static void init_sound( void )
3842 SignedByte permission = fsRdPerm;
3848 /* Descend into "lib" folder */
3849 pb.dirInfo.ioCompletion = NULL;
3850 pb.dirInfo.ioNamePtr = "\plib";
3851 pb.dirInfo.ioVRefNum = app_vol;
3852 pb.dirInfo.ioDrDirID = app_dir;
3853 pb.dirInfo.ioFDirIndex = 0;
3855 /* Check for errors */
3856 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3859 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3861 /* Descend into "lib/save" folder */
3862 pb.dirInfo.ioCompletion = NULL;
3863 pb.dirInfo.ioNamePtr = "\pxtra";
3864 pb.dirInfo.ioVRefNum = app_vol;
3865 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3866 pb.dirInfo.ioFDirIndex = 0;
3868 /* Check for errors */
3869 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3872 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3874 /* Descend into "lib/save" folder */
3875 pb.dirInfo.ioCompletion = NULL;
3876 pb.dirInfo.ioNamePtr = "\psound";
3877 pb.dirInfo.ioVRefNum = app_vol;
3878 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3879 pb.dirInfo.ioFDirIndex = 0;
3881 /* Check for errors */
3882 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3885 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3887 ret = HOpenResFile( app_vol , pb.dirInfo.ioDrDirID , "\psound.rsrc" , permission );
3891 for( i = 0 ; i < 7 ; i++ )
3892 soundmode[i] = false;
3894 for( i = 1 ; i < SOUND_MAX ; i++ ){
3895 /* Get the proper sound name */
3896 sprintf((char*)sound + 1, "%.16s.wav", angband_sound_name[i]);
3897 sound[0] = strlen((char*)sound + 1);
3899 /* Obtain resource XXX XXX XXX */
3900 handle = Get1NamedResource('snd ', sound);
3901 if( handle == NULL || ext_sound )
3902 handle = GetNamedResource('snd ', sound);
3905 soundmode[soundchoice[i]] = true;
3914 static void init_graf( void )
3918 SignedByte permission = fsRdPerm;
3924 /* Descend into "lib" folder */
3925 pb.dirInfo.ioCompletion = NULL;
3926 pb.dirInfo.ioNamePtr = "\plib";
3927 pb.dirInfo.ioVRefNum = app_vol;
3928 pb.dirInfo.ioDrDirID = app_dir;
3929 pb.dirInfo.ioFDirIndex = 0;
3931 /* Check for errors */
3932 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3935 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3937 /* Descend into "lib/xtra" folder */
3938 pb.dirInfo.ioCompletion = NULL;
3939 pb.dirInfo.ioNamePtr = "\pxtra";
3940 pb.dirInfo.ioVRefNum = app_vol;
3941 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3942 pb.dirInfo.ioFDirIndex = 0;
3944 /* Check for errors */
3945 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3948 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3950 /* Descend into "lib/xtra/graf" folder */
3951 pb.dirInfo.ioCompletion = NULL;
3952 pb.dirInfo.ioNamePtr = "\pgraf";
3953 pb.dirInfo.ioVRefNum = app_vol;
3954 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3955 pb.dirInfo.ioFDirIndex = 0;
3957 /* Check for errors */
3958 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3961 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3963 ret = HOpenResFile( app_vol , pb.dirInfo.ioDrDirID , "\pgraf.rsrc" , permission );
3968 /* Obtain resource XXX XXX XXX */
3969 handle = Get1NamedResource('PICT', graf);
3970 if ( handle == NULL || ext_graf )
3971 handle = GetNamedResource('PICT', "\pgraf.rsrc");
3978 #endif /* MACH_O_CARBON */
3984 static void init_chuukei( void )
3990 path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "chuukei.txt");
3992 fp = fopen(path, "r");
3997 if (fgets(tmp, 1024, fp)){
3999 int n = strlen(tmp);
4005 chuukei_server = TRUE;
4006 if(connect_chuukei_server(&tmp[2])<0){
4007 msg_print("connect fail");
4010 msg_print("connect");
4017 chuukei_client = TRUE;
4018 connect_chuukei_server(&tmp[2]);
4034 short InevrtCheck( DialogPtr targetDlg, short check )
4041 GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
4042 result = (GetControlValue( (ControlHandle)checkH ) + 1 ) % 2;
4043 SetControlValue( (ControlHandle)checkH , result );
4051 short SetCheck( DialogPtr targetDlg, short check, long result )
4058 GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
4059 SetControlValue( (ControlHandle)checkH , result );
4067 short GetCheck( DialogPtr targetDlg, short check )
4074 GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
4075 result = GetControlValue( (ControlHandle)checkH );
4079 void SoundConfigDLog(void)
4085 dialog=GetNewDialog(131, 0, (WindowPtr)-1);
4086 SetDialogDefaultItem( dialog, ok );
4087 SetDialogCancelItem( dialog, cancel );
4088 for( i = 1 ; i < 7 ; i++ )
4089 SetCheck( dialog, i+2 , soundmode[i] );
4091 /* ShowWindow(dialog); */
4092 for( item_hit = 100 ; cancel < item_hit ; ){
4093 ModalDialog(0, &item_hit);
4097 for( i = 1 ; i < 7 ; i++ )
4098 soundmode[i] = GetCheck( dialog, i+2 );
4103 InevrtCheck( dialog, item_hit );
4106 DisposeDialog(dialog);
4114 #if TARGET_API_MAC_CARBON
4115 static void save_pref_file(void)
4120 static void save_pref_file(void)
4129 /* Assume failure */
4132 /* Assume failure */
4149 /* Find the folder */
4150 err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
4156 /* Extract a path name */
4157 PathNameFromDirID(dirID, vref, (StringPtr)foo);
4159 /* Convert the string */
4160 ptocstr((StringPtr)foo);
4162 /* Append the preference file name */
4163 strcat(foo, PREF_FILE_NAME);
4165 /* Open the preference file */
4166 /* my_fopen set file type and file creator for MPW */
4167 fff = my_fopen(foo, "w");
4174 #endif /* USE_SFL_CODE */
4180 HGetVol(0, &savev, &saved);
4182 /* Go to "system" folder */
4183 SysEnvirons(curSysEnvVers, &env);
4184 SetVol(0, env.sysVRefNum);
4186 /* Open the preference file */
4187 /* my_fopen set file type and file creator for MPW */
4188 fff = fopen(PREF_FILE_NAME, "w");
4191 HSetVol(0, savev, saved);
4194 /* Save preferences */
4197 /* Write the preferences */
4208 #if defined(__MWERKS__)
4211 * A simple "Yes/No" filter to parse "key press" events in dialog windows
4213 static pascal Boolean ynfilter(DialogPtr dialog, EventRecord *event, short *ip)
4215 /* Parse key press events */
4216 if (event->what == keyDown)
4221 /* Extract the pressed key */
4222 c = (event->message & charCodeMask);
4224 /* Accept "no" and <return> and <enter> */
4225 if ((c=='n') || (c=='N') || (c==13) || (c==3)) i = 1;
4228 else if ((c=='y') || (c=='Y')) i = 2;
4230 /* Handle "yes" or "no" */
4234 ControlHandle control;
4237 /* Get the button */
4238 GetDialogItem(dialog, i, &type, (Handle*)&control, &r);
4240 /* Blink button for 1/10 second */
4241 HiliteControl(control, 1);
4242 Term_xtra_mac(TERM_XTRA_DELAY, 100);
4243 HiliteControl(control, 0);
4255 #endif /* __MWERKS__ */
4258 #if TARGET_API_MAC_CARBON
4261 * Prepare savefile dialogue and set the variable
4262 * savefile accordingly. Returns true if it succeeds, false (or
4263 * aborts) otherwise. If all is false, only allow files whose type
4265 * Originally written by Peter Ammon
4267 static bool select_savefile(bool all)
4270 FSSpec theFolderSpec;
4271 FSSpec savedGameSpec;
4272 NavDialogOptions dialogOptions;
4273 NavReplyRecord reply;
4274 /* Used only when 'all' is true */
4275 NavTypeList types = {ANGBAND_CREATOR, 1, 1, {'SAVE'}};
4276 NavTypeListHandle myTypeList;
4277 AEDesc defaultLocation;
4279 #ifdef MACH_O_CARBON
4281 /* Find the save folder */
4282 err = path_to_spec(ANGBAND_DIR_SAVE, &theFolderSpec);
4286 /* Find :lib:save: folder */
4287 err = FSMakeFSSpec(app_vol, app_dir, "\p:lib:save:", &theFolderSpec);
4292 if (err != noErr) quit("Unable to find the folder :lib:save:");
4294 /* Get default Navigator dialog options */
4295 err = NavGetDefaultDialogOptions(&dialogOptions);
4297 /* Clear preview option */
4298 dialogOptions.dialogOptionFlags &= ~kNavAllowPreviews;
4300 /* Disable multiple file selection */
4301 dialogOptions.dialogOptionFlags &= ~kNavAllowMultipleFiles;
4303 /* Make descriptor for default location */
4304 err = AECreateDesc(typeFSS, &theFolderSpec, sizeof(FSSpec),
4308 if (err != noErr) quit("Unable to allocate descriptor");
4310 /* We are indifferent to signature and file types */
4313 myTypeList = (NavTypeListHandle)nil;
4316 /* Set up type handle */
4319 err = PtrToHand(&types, (Handle *)&myTypeList, sizeof(NavTypeList));
4322 if (err != noErr) quit("Error in PtrToHand. Try enlarging heap");
4326 /* Call NavGetFile() with the types list */
4327 err = NavChooseFile(&defaultLocation, &reply, &dialogOptions, NULL,
4328 NULL, NULL, myTypeList, NULL);
4330 /* Free type list */
4331 if (!all) DisposeHandle((Handle)myTypeList);
4339 /* Invalid response -- allow the user to cancel */
4340 else if (!reply.validRecord)
4342 /* Hack -- Fake error */
4346 /* Retrieve FSSpec from the reply */
4349 AEKeyword theKeyword;
4350 DescType actualType;
4353 /* Get a pointer to selected file */
4354 (void)AEGetNthPtr(&reply.selection, 1, typeFSS, &theKeyword,
4355 &actualType, &savedGameSpec, sizeof(FSSpec), &actualSize);
4357 /* Dispose NavReplyRecord, resources and descriptors */
4358 (void)NavDisposeReply(&reply);
4361 /* Dispose location info */
4362 AEDisposeDesc(&defaultLocation);
4365 if (err != noErr) return (FALSE);
4367 #ifdef MACH_O_CARBON
4369 /* Convert FSSpec to pathname and store it in variable savefile */
4370 (void)spec_to_path(&savedGameSpec, savefile, sizeof(savefile));
4374 /* Convert FSSpec to pathname and store it in variable savefile */
4377 savedGameSpec.parID,
4378 savedGameSpec.vRefNum,
4379 (char *)savedGameSpec.name);
4390 * Handle menu: "File" + "New"
4392 static void do_menu_file_new(void)
4397 /* Game is in progress */
4398 game_in_progress = 1;
4412 * Handle menu: "File" + "Open"
4414 #if TARGET_API_MAC_CARBON
4415 static void do_menu_file_open(bool all)
4417 /* Let the player to choose savefile */
4418 if (!select_savefile(all)) return;
4423 /* Game is in progress */
4424 game_in_progress = TRUE;
4436 static void do_menu_file_open(bool all)
4450 /* vrefnum = GetSFCurVol(); */
4451 vrefnum = -*((short*)0x214);
4453 /* drefnum = GetSFCurDir(); */
4454 drefnum = *((long*)0x398);
4456 /* Descend into "lib" folder */
4457 pb.ioCompletion = NULL;
4458 pb.ioNamePtr = "\plib";
4459 pb.ioVRefNum = vrefnum;
4460 pb.ioDrDirID = drefnum;
4463 /* Check for errors */
4464 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
4467 if ((err == noErr) && (pb.ioFlAttrib & 0x10))
4469 /* Descend into "lib/save" folder */
4470 pb.ioCompletion = NULL;
4471 pb.ioNamePtr = "\psave";
4472 pb.ioVRefNum = vrefnum;
4473 pb.ioDrDirID = pb.ioDrDirID;
4476 /* Check for errors */
4477 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
4480 if ((err == noErr) && (pb.ioFlAttrib & 0x10))
4482 /* SetSFCurDir(pb.ioDrDirID); */
4483 *((long*)0x398) = pb.ioDrDirID;
4487 /* Window location */
4488 topleft.h = (qd.screenBits.bounds.left+qd.screenBits.bounds.right)/2-344/2;
4489 topleft.v = (2*qd.screenBits.bounds.top+qd.screenBits.bounds.bottom)/3-188/2;
4491 /* Allow "all" files */
4495 SFGetFile(topleft, "\p", NULL, -1, types, NULL, &reply);
4498 /* Allow "save" files */
4505 SFGetFile(topleft, "\p", NULL, 1, types, NULL, &reply);
4509 if (!reply.good) return;
4511 /* Extract textual file name for save file */
4512 GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
4513 refnum_to_name(savefile, drefnum, vrefnum, (char*)reply.fName);
4518 /* Game is in progress */
4519 game_in_progress = 1;
4534 * Handle the "open_when_ready" flag
4536 static void handle_open_when_ready(void)
4538 /* Check the flag XXX XXX XXX make a function for this */
4539 if (open_when_ready && initialized && !game_in_progress)
4542 open_when_ready = FALSE;
4544 /* Game is in progress */
4545 game_in_progress = 1;
4564 * Initialize the menus
4566 * Apple (128) = { About, -, ... }
4567 * File (129) = { New,Open,Import,Close,Save,-,Exit,Quit }
4568 * Edit (130) = { Cut, Copy, Paste, Clear } (?)
4569 * Font (131) = { Bold, Extend, -, Monaco, ..., -, ... }
4570 * Size (132) = { ... }
4571 * Window (133) = { Angband, Mirror, Recall, Choice,
4572 * Term-4, Term-5, Term-6, Term-7 }
4573 * Special (134) = { Sound, Graphics, TileWidth, TileHeight, -,
4578 #define MENU_APPLE 128
4579 #define ITEM_ABOUT 1
4582 #define MENU_FILE 129
4584 # define ITEM_OPEN 2
4585 # define ITEM_IMPORT 3
4586 # define ITEM_CLOSE 4
4587 # define ITEM_SAVE 5
4588 # define ITEM_QUIT 7
4591 #define MENU_EDIT 130
4592 # define ITEM_UNDO 1
4594 # define ITEM_COPY 4
4595 # define ITEM_PASTE 5
4596 # define ITEM_CLEAR 6
4599 #define MENU_FONT 131
4600 # define ITEM_BOLD 1
4601 # define ITEM_WIDE 2
4604 #define MENU_SIZE 132
4607 #define MENU_WINDOWS 133
4610 #define MENU_SPECIAL 134
4611 # define ITEM_SOUND 1
4612 # define ITEM_GRAPH 2
4613 # define ITEM_TILEWIDTH 3
4614 # define ITEM_TILEHEIGHT 4
4615 # define ITEM_FIDDLE 6
4616 # define ITEM_WIZARD 7
4618 /* Sounds submenu */
4619 #define SUBMENU_SOUND 143
4620 # define ITEM_USE_SOUND 1
4621 # define ITEM_SOUND_SETTING 2
4623 /* Graphics submenu */
4624 #define SUBMENU_GRAPH 144
4625 # define ITEM_NONE 1
4627 # define ITEM_16X16 3
4628 # define ITEM_BIGTILE 5
4630 /* TileWidth submenu */
4631 #define SUBMENU_TILEWIDTH 145
4633 /* TileHeight submenu */
4634 #define SUBMENU_TILEHEIGHT 146
4637 static void init_menubar(void)
4649 #if TARGET_API_MAC_CARBON
4654 /* Get the "apple" menu */
4655 mbar = GetNewMBar(128);
4659 if (mbar == nil) quit("¥á¥Ë¥å¡¼¥Ð¡¼ ID 128¤ò¸«¤Ä¤±¤ë»ö¤¬¤Ç¤¤Þ¤»¤ó!");
4661 if (mbar == nil) quit("Cannot find menubar('MBAR') id 128!");
4664 /* Insert them into the current menu list */
4668 DisposeHandle(mbar);
4670 #if !TARGET_API_MAC_CARBON
4671 /* Apple menu (id 128) */
4672 m = GetMenuHandle(MENU_APPLE);
4674 /* Add the DA's to the "apple" menu */
4675 AppendResMenu (m, 'DRVR');
4678 /* Get the "File" menu */
4679 #if TARGET_API_MAC_CARBON
4680 m = GetMenuHandle(MENU_FILE);
4681 err = Gestalt( gestaltSystemVersion, &response );
4682 if ( (err == noErr) && (response >= 0x00000A00) )
4684 DeleteMenuItem(m, ITEM_QUIT);
4688 /* Edit menu (id 130) - we don't have to do anything */
4691 * Font menu (id 131) - append names of mono-spaced fonts
4692 * followed by all available ones
4694 m = GetMenuHandle(MENU_FONT);
4697 r.left = r.right = r.top = r.bottom = 0;
4699 /* Make the fake window */
4700 tmpw = NewWindow(0, &r, "\p", false, documentProc, 0, 0, 0);
4702 /* Activate the "fake" window */
4703 #if TARGET_API_MAC_CARBON
4704 SetPortWindowPort(tmpw);
4715 /* Add the fonts to the menu */
4716 AppendResMenu(m, 'FONT');
4719 #if TARGET_API_MAC_CARBON
4720 n = CountMenuItems(m);
4726 for (i = n; i >= 4; i--)
4731 /* Acquire the font name */
4732 GetMenuItemText(m, i, tmpName);
4734 /* Acquire the font index */
4735 #if TARGET_API_MAC_CARBON
4736 fontNum = FMGetFontFamilyFromName( tmpName );
4738 GetFNum(tmpName, &fontNum);
4741 /* Apply the font index */
4744 /* Remove non-mono-spaced fonts */
4745 if ((CharWidth('i') != CharWidth('W')) || (CharWidth('W') == 0))
4747 /* Delete the menu item XXX XXX XXX */
4748 DeleteMenuItem (m, i);
4752 /* Destroy the old window */
4753 DisposeWindow(tmpw);
4755 /* Add a separator */
4756 AppendMenu(m, "\p-");
4758 /* Add the fonts to the menu */
4759 AppendResMenu (m, 'FONT');
4762 /* Size menu (id 132) */
4763 m = GetMenuHandle(MENU_SIZE);
4765 /* Add some sizes (stagger choices) */
4766 for (i = 8; i <= 32; i += ((i / 16) + 1))
4771 sprintf((char*)buf + 1, "%d", i);
4772 buf[0] = strlen((char*)buf + 1);
4779 /* Windows menu (id 133) */
4780 m = GetMenuHandle(MENU_WINDOWS);
4782 /* Default choices */
4783 for (i = 0; i < MAX_TERM_DATA; i++)
4787 /* Describe the item */
4788 sprintf((char*)buf + 1, "%.15s", angband_term_name[i]);
4789 buf[0] = strlen((char*)buf + 1);
4794 /* Command-Key shortcuts */
4795 if (i < 8) SetItemCmd(m, i + 1, '0' + i);
4799 #if TARGET_API_MAC_CARBON && !defined(MAC_MPW)
4801 /* CW or gcc -- Use recommended interface for hierarchical menus */
4803 /* Special menu (id 134) */
4804 m = GetMenuHandle(MENU_SPECIAL);
4806 /* Insert Graphics submenu (id 143) */
4810 /* Get the submenu */
4811 submenu = GetMenu(SUBMENU_SOUND);
4814 SetMenuItemHierarchicalMenu(m, ITEM_SOUND, submenu);
4817 /* Insert Graphics submenu (id 144) */
4821 /* Get the submenu */
4822 submenu = GetMenu(SUBMENU_GRAPH);
4825 SetMenuItemHierarchicalMenu(m, ITEM_GRAPH, submenu);
4828 /* Insert TileWidth submenu (id 145) */
4832 /* Get the submenu */
4833 submenu = GetMenu(SUBMENU_TILEWIDTH);
4835 /* Add some sizes */
4836 for (i = 4, n = 1; i <= 32; i++, n++)
4841 strnfmt((char*)buf + 1, 15, "%d", i);
4842 buf[0] = strlen((char*)buf + 1);
4845 AppendMenu(submenu, buf);
4849 SetMenuItemHierarchicalMenu(m, ITEM_TILEWIDTH, submenu);
4852 /* Insert TileHeight submenu (id 146) */
4856 /* Get the submenu */
4857 submenu = GetMenu(SUBMENU_TILEHEIGHT);
4860 /* Add some sizes */
4861 for (i = 4, n = 1; i <= 32; i++, n++)
4866 strnfmt((char*)buf + 1, 15, "%d", i);
4867 buf[0] = strlen((char*)buf + 1);
4870 AppendMenu(submenu, buf);
4874 SetMenuItemHierarchicalMenu(m, ITEM_TILEHEIGHT, submenu);
4879 /* Special menu (id 134) */
4881 /* Get graphics (sub)menu (id 143) */
4882 m = GetMenu(SUBMENU_SOUND);
4884 /* Insert it as a submenu */
4885 InsertMenu(m, hierMenu);
4888 /* Get graphics (sub)menu (id 144) */
4889 m = GetMenu(SUBMENU_GRAPH);
4891 /* Insert it as a submenu */
4892 InsertMenu(m, hierMenu);
4895 /* Get TileWidth (sub)menu (id 145) */
4896 m = GetMenu(SUBMENU_TILEWIDTH);
4898 /* Add some sizes */
4899 for (i = 4; i <= 32; i++)
4904 sprintf((char*)buf + 1, "%d", i);
4905 buf[0] = strlen((char*)buf + 1);
4912 /* Insert it as a submenu */
4913 InsertMenu(m, hierMenu);
4915 /* Get TileHeight (sub)menu (id 146) */
4916 m = GetMenu(SUBMENU_TILEHEIGHT);
4918 /* Add some sizes */
4919 for (i = 4; i <= 32; i++)
4924 sprintf((char*)buf + 1, "%d", i);
4925 buf[0] = strlen((char*)buf + 1);
4932 /* Insert the menu */
4933 InsertMenu(m, hierMenu);
4936 /* Update the menu bar */
4944 static void setup_menus(void)
4954 term_data *td = NULL;
4957 /* Relevant "term_data" */
4958 for (i = 0; i < MAX_TERM_DATA; i++)
4961 if (!data[i].t) continue;
4963 /* Notice the matching window */
4964 if (data[i].w == FrontWindow()) td = &data[i];
4969 m = GetMenuHandle(MENU_FILE);
4972 #if TARGET_API_MAC_CARBON
4973 n = CountMenuItems(m);
4979 for (i = 1; i <= n; i++)
4982 #if TARGET_API_MAC_CARBON
4983 DisableMenuItem(m, i);
4984 CheckMenuItem(m, i, FALSE);
4987 CheckItem(m, i, FALSE);
4991 /* Enable "new"/"open..."/"import..." */
4992 if (initialized && !game_in_progress)
4994 #if TARGET_API_MAC_CARBON
4995 EnableMenuItem(m, ITEM_NEW);
4996 EnableMenuItem(m, ITEM_OPEN);
4997 EnableMenuItem(m, ITEM_IMPORT);
4999 EnableItem(m, ITEM_NEW);
5000 EnableItem(m, ITEM_OPEN);
5001 EnableItem(m, ITEM_IMPORT);
5005 /* Enable "close" */
5008 #if TARGET_API_MAC_CARBON
5009 EnableMenuItem(m, ITEM_CLOSE);
5011 EnableItem(m, ITEM_CLOSE);
5016 if (initialized && character_generated)
5018 #if TARGET_API_MAC_CARBON
5019 EnableMenuItem(m, ITEM_SAVE);
5021 EnableItem(m, ITEM_SAVE);
5028 #if TARGET_API_MAC_CARBON
5029 EnableMenuItem(m, ITEM_QUIT);
5031 EnableItem(m, ITEM_QUIT);
5037 m = GetMenuHandle(MENU_EDIT);
5040 #if TARGET_API_MAC_CARBON
5041 n = CountMenuItems(m);
5047 for (i = 1; i <= n; i++)
5050 #if TARGET_API_MAC_CARBON
5051 DisableMenuItem(m, i);
5052 CheckMenuItem(m, i, FALSE);
5055 CheckItem(m, i, FALSE);
5059 /* Enable "edit" options if "needed" */
5062 #if TARGET_API_MAC_CARBON
5063 EnableMenuItem(m, ITEM_UNDO);
5064 EnableMenuItem(m, ITEM_CUT);
5065 EnableMenuItem(m, ITEM_COPY);
5066 EnableMenuItem(m, ITEM_PASTE);
5067 EnableMenuItem(m, ITEM_CLEAR);
5069 EnableItem(m, ITEM_UNDO);
5070 EnableItem(m, ITEM_CUT);
5071 EnableItem(m, ITEM_COPY);
5072 EnableItem(m, ITEM_PASTE);
5073 EnableItem(m, ITEM_CLEAR);
5079 m = GetMenuHandle(MENU_FONT);
5082 #if TARGET_API_MAC_CARBON
5083 n = CountMenuItems(m);
5089 for (i = 1; i <= n; i++)
5092 #if TARGET_API_MAC_CARBON
5093 DisableMenuItem(m, i);
5094 CheckMenuItem(m, i, FALSE);
5097 CheckItem(m, i, FALSE);
5101 /* Hack -- look cute XXX XXX */
5102 /* SetItemStyle(m, 1, bold); */
5104 /* Hack -- look cute XXX XXX */
5105 /* SetItemStyle(m, 2, extend); */
5110 #if TARGET_API_MAC_CARBON
5112 EnableMenuItem(m, ITEM_BOLD);
5114 /* Enable "extend" */
5115 EnableMenuItem(m, ITEM_WIDE);
5117 /* Check the appropriate "bold-ness" */
5118 if (td->font_face & bold) CheckMenuItem(m, ITEM_BOLD, TRUE);
5120 /* Check the appropriate "wide-ness" */
5121 if (td->font_face & extend) CheckMenuItem(m, ITEM_WIDE, TRUE);
5124 for (i = 4; i <= n; i++)
5127 EnableMenuItem(m, i);
5130 GetMenuItemText(m, i, s);
5133 /* Check active font */
5134 if (td->font_id == value) CheckMenuItem(m, i, TRUE);
5138 EnableItem(m, ITEM_BOLD);
5140 /* Enable "extend" */
5141 EnableItem(m, ITEM_WIDE);
5143 /* Check the appropriate "bold-ness" */
5144 if (td->font_face & bold) CheckItem(m, ITEM_BOLD, TRUE);
5146 /* Check the appropriate "wide-ness" */
5147 if (td->font_face & extend) CheckItem(m, ITEM_WIDE, TRUE);
5150 for (i = 4; i <= n; i++)
5156 GetMenuItemText(m, i, s);
5159 /* Check active font */
5160 if (td->font_id == value) CheckItem(m, i, TRUE);
5167 m = GetMenuHandle(MENU_SIZE);
5170 #if TARGET_API_MAC_CARBON
5171 n = CountMenuItems(m);
5177 for (i = 1; i <= n; i++)
5180 #if TARGET_API_MAC_CARBON
5181 DisableMenuItem(m, i);
5182 CheckMenuItem(m, i, FALSE);
5185 CheckItem(m, i, FALSE);
5193 for (i = 1; i <= n; i++)
5196 GetMenuItemText(m, i, s);
5198 value = atoi((char*)(s+1));
5200 #if TARGET_API_MAC_CARBON
5201 /* Enable the "real" sizes */
5202 if (RealFont(td->font_id, value)) EnableMenuItem(m, i);
5204 /* Check the current size */
5205 if (td->font_size == value) CheckMenuItem(m, i, TRUE);
5207 /* Enable the "real" sizes */
5208 if (RealFont(td->font_id, value)) EnableItem(m, i);
5210 /* Check the current size */
5211 if (td->font_size == value) CheckItem(m, i, TRUE);
5218 m = GetMenuHandle(MENU_WINDOWS);
5221 #if TARGET_API_MAC_CARBON
5222 n = CountMenuItems(m);
5227 /* Check active windows */
5228 for (i = 1; i <= n; i++)
5230 /* Check if needed */
5231 #if TARGET_API_MAC_CARBON
5232 CheckMenuItem(m, i, data[i-1].mapped);
5234 CheckItem(m, i, data[i-1].mapped);
5240 m = GetMenuHandle(MENU_SPECIAL);
5243 #if TARGET_API_MAC_CARBON
5244 n = CountMenuItems(m);
5250 for (i = 1; i <= n; i++)
5253 #if TARGET_API_MAC_CARBON
5254 DisableMenuItem(m, i);
5257 /* XXX Oh no, this removes submenu... */
5258 if ((i != ITEM_SOUND) &&
5259 (i != ITEM_GRAPH) &&
5260 (i != ITEM_TILEWIDTH) &&
5261 (i != ITEM_TILEHEIGHT)) CheckMenuItem(m, i, FALSE);
5264 CheckMenuItem(m, i, FALSE);
5270 /* XXX Oh no, this removes submenu... */
5271 if ((i != ITEM_SOUND) &&
5272 (i != ITEM_GRAPH) &&
5273 (i != ITEM_TILEWIDTH) &&
5274 (i != ITEM_TILEHEIGHT)) CheckItem(m, i, FALSE);
5278 #if TARGET_API_MAC_CARBON
5279 /* Item "arg_sound" */
5280 EnableMenuItem(m, ITEM_SOUND);
5286 /* MPW's Universal Interface is a bit out of date */
5288 /* Graphics submenu */
5289 submenu = GetMenuHandle(SUBMENU_SOUND);
5293 /* Graphics submenu */
5294 (void)GetMenuItemHierarchicalMenu(m, ITEM_SOUND, &submenu);
5299 n = CountMenuItems(submenu);
5302 for (i = 1; i <= n; i++)
5305 DisableMenuItem(submenu, i);
5306 CheckMenuItem(submenu, i, FALSE);
5309 /* Item "Sound On/Off" */
5310 EnableMenuItem(submenu, ITEM_USE_SOUND);
5311 CheckMenuItem(submenu, ITEM_USE_SOUND, arg_sound);
5313 /* Item "Sounf Config" */
5314 #ifndef MACH_O_CARBON
5315 EnableMenuItem(submenu, ITEM_SOUND_SETTING);
5319 /* Item "Graphics" */
5320 EnableMenuItem(m, ITEM_GRAPH);
5326 /* MPW's Universal Interface is a bit out of date */
5328 /* Graphics submenu */
5329 submenu = GetMenuHandle(SUBMENU_GRAPH);
5333 /* Graphics submenu */
5334 (void)GetMenuItemHierarchicalMenu(m, ITEM_GRAPH, &submenu);
5339 n = CountMenuItems(submenu);
5342 for (i = 1; i <= n; i++)
5345 DisableMenuItem(submenu, i);
5346 CheckMenuItem(submenu, i, FALSE);
5350 EnableMenuItem(submenu, ITEM_NONE);
5351 CheckMenuItem(submenu, ITEM_NONE, (graf_mode == GRAF_MODE_NONE));
5354 EnableMenuItem(submenu, ITEM_8X8);
5355 CheckMenuItem(submenu, ITEM_8X8, (graf_mode == GRAF_MODE_8X8));
5358 EnableMenuItem(submenu, ITEM_16X16);
5359 CheckMenuItem(submenu, ITEM_16X16, (graf_mode == GRAF_MODE_16X16));
5361 /* Item "Big tiles" */
5362 EnableMenuItem(submenu, ITEM_BIGTILE);
5363 CheckMenuItem(submenu, ITEM_BIGTILE, arg_bigtile);
5366 /* Item "TileWidth" */
5367 EnableMenuItem(m, ITEM_TILEWIDTH);
5373 /* MPW's Universal Interface is a bit out of date */
5375 /* TIleWidth submenu */
5376 submenu = GetMenuHandle(SUBMENU_TILEWIDTH);
5380 /* TileWidth submenu */
5381 (void)GetMenuItemHierarchicalMenu(m, ITEM_TILEWIDTH, &submenu);
5386 n = CountMenuItems(submenu);
5389 for (i = 1; i <= n; i++)
5392 DisableMenuItem(submenu, i);
5393 CheckMenuItem(submenu, i, FALSE);
5400 for (i = 1; i <= n; i++)
5403 /* GetMenuItemText(m,i,s); */
5404 GetMenuItemText(submenu, i, s);
5406 value = atoi((char*)(s+1));
5409 if (value >= td->font_wid) EnableMenuItem(submenu, i);
5411 /* Check the current size */
5412 if (td->tile_wid == value) CheckMenuItem(submenu, i, TRUE);
5417 /* Item "TileHeight" */
5418 EnableMenuItem(m, ITEM_TILEHEIGHT);
5424 /* MPW's Universal Interface is a bit out of date */
5426 /* TileHeight submenu */
5427 submenu = GetMenuHandle(SUBMENU_TILEHEIGHT);
5431 /* TileWidth submenu */
5432 (void)GetMenuItemHierarchicalMenu(m, ITEM_TILEHEIGHT, &submenu);
5437 n = CountMenuItems(submenu);
5440 for (i = 1; i <= n; i++)
5443 DisableMenuItem(submenu, i);
5444 CheckMenuItem(submenu, i, FALSE);
5451 for (i = 1; i <= n; i++)
5454 /* GetMenuItemText(m,i,s); */
5455 GetMenuItemText(submenu, i, s);
5457 value = atoi((char*)(s+1));
5460 if (value >= td->font_hgt) EnableMenuItem(submenu, i);
5462 /* Check the current size */
5463 if (td->tile_hgt == value) CheckMenuItem(submenu, i, TRUE);
5468 /* Item "arg_fiddle" */
5469 EnableMenuItem(m, ITEM_FIDDLE);
5470 CheckMenuItem(m, ITEM_FIDDLE, arg_fiddle);
5472 /* Item "arg_wizard" */
5473 EnableMenuItem(m, ITEM_WIZARD);
5474 CheckMenuItem(m, ITEM_WIZARD, arg_wizard);
5477 /* Item "arg_sound" */
5478 EnableItem(m, ITEM_SOUND);
5480 /* Item "arg_graphics" */
5481 EnableItem(m, ITEM_GRAPH);
5483 /* Item "TileWidth" */
5484 EnableItem(m, ITEM_TILEWIDTH);
5486 /* Item "TileHeight" */
5487 EnableItem(m, ITEM_TILEHEIGHT);
5489 /* Item "arg_fiddle" */
5490 EnableItem(m, ITEM_FIDDLE);
5491 CheckItem(m, ITEM_FIDDLE, arg_fiddle);
5493 /* Item "arg_wizard" */
5494 EnableItem(m, ITEM_WIZARD);
5495 CheckItem(m, ITEM_WIZARD, arg_wizard);
5497 /* Sounds submenu */
5498 m = GetMenuHandle(SUBMENU_SOUND);
5504 for (i = 1; i <= n; i++)
5508 CheckItem(m, i, FALSE);
5511 /* Item "Sound On/Off" */
5512 EnableItem(m, ITEM_USE_SOUND);
5513 CheckItem(m, ITEM_USE_SOUND, arg_sound);
5515 /* Item "Sound Config" */
5516 EnableItem(m, ITEM_SOUND_SETTING);
5518 /* Graphics submenu */
5519 m = GetMenuHandle(SUBMENU_GRAPH);
5525 for (i = 1; i <= n; i++)
5529 CheckItem(m, i, FALSE);
5533 EnableItem(m, ITEM_NONE);
5534 CheckItem(m, ITEM_NONE, (graf_mode == GRAF_MODE_NONE));
5537 EnableItem(m, ITEM_8X8);
5538 CheckItem(m, ITEM_8X8, (graf_mode == GRAF_MODE_8X8));
5541 EnableItem(m, ITEM_16X16);
5542 CheckItem(m, ITEM_16X16, (graf_mode == GRAF_MODE_16X16));
5544 /* Item "Bigtile" */
5545 EnableItem(m, ITEM_BIGTILE);
5546 CheckItem(m, ITEM_BIGTILE, arg_bigtile);
5549 /* TIleWidth submenu */
5550 m = GetMenuHandle(SUBMENU_TILEWIDTH);
5556 for (i = 1; i <= n; i++)
5560 CheckItem(m, i, FALSE);
5567 for (i = 1; i <= n; i++)
5570 /* GetMenuItemText(m,i,s); */
5571 GetMenuItemText(m, i, s);
5573 value = atoi((char*)(s+1));
5576 if (value >= td->font_wid) EnableItem(m, i);
5578 /* Check the current size */
5579 if (td->tile_wid == value) CheckItem(m, i, TRUE);
5584 /* TileHeight submenu */
5585 m = GetMenuHandle(SUBMENU_TILEHEIGHT);
5591 for (i = 1; i <= n; i++)
5595 CheckItem(m, i, FALSE);
5602 for (i = 1; i <= n; i++)
5605 GetMenuItemText(m, i, s);
5607 value = atoi((char*)(s+1));
5610 if (value >= td->font_hgt) EnableItem(m, i);
5612 /* Check the current size */
5613 if (td->tile_hgt == value) CheckItem(m, i, TRUE);
5622 * Process a menu selection (see above)
5624 * Hack -- assume that invalid menu selections are disabled above,
5625 * which I have been informed may not be reliable. XXX XXX XXX
5627 static void menu(long mc)
5631 int menuid, selection;
5633 static unsigned char s[1000];
5637 term_data *td = NULL;
5642 /* Analyze the menu command */
5643 menuid = HiWord(mc);
5644 selection = LoWord(mc);
5647 /* Find the window */
5648 for (i = 0; i < MAX_TERM_DATA; i++)
5650 /* Skip dead windows */
5651 if (!data[i].t) continue;
5653 /* Notice matches */
5654 if (data[i].w == FrontWindow()) td = &data[i];
5658 /* Branch on the menu */
5664 /* About Angband... */
5665 #if TARGET_API_MAC_CARBON
5666 if (selection == ITEM_ABOUT)
5671 /* Get the about dialogue */
5672 dialog=GetNewDialog(128, 0, (WindowPtr)-1);
5674 /* Move it to the middle of the screen */
5676 GetDialogWindow(dialog),
5678 kWindowCenterOnMainScreen);
5680 /* Show the dialog */
5681 TransitionWindow(GetDialogWindow(dialog),
5682 kWindowZoomTransitionEffect,
5683 kWindowShowTransitionAction,
5686 /* Wait for user to click on it */
5687 ModalDialog(0, &item_hit);
5689 /* Free the dialogue */
5690 DisposeDialog(dialog);
5694 if (selection == ITEM_ABOUT)
5700 dialog=GetNewDialog(128, 0, (WindowPtr)-1);
5703 center_rect(&r, &qd.screenBits.bounds);
5704 MoveWindow(dialog, r.left, r.top, 1);
5706 ModalDialog(0, &item_hit);
5707 DisposeDialog(dialog);
5711 /* Desk accessory */
5712 GetMenuItemText(GetMenuHandle(MENU_APPLE), selection, s);
5733 do_menu_file_open(FALSE);
5740 do_menu_file_open(TRUE);
5754 td->t->mapped_flag = FALSE;
5756 /* Hide the window */
5767 plog("º£¤Ï¥»¡¼¥Ö¤¹¤ë¤³¤È¤Ï½ÐÍè¤Þ¤»¤ó¡£");
5769 plog("You may not do that right now.");
5774 /* Hack -- Forget messages */
5777 /* Hack -- Save the game */
5778 do_cmd_save_game(FALSE);
5783 /* Quit (with save) */
5786 /* Save the game (if necessary) */
5787 if (game_in_progress && character_generated)
5791 plog("º£¤Ï¥»¡¼¥Ö¤¹¤ë¤³¤È¤Ï½ÐÍè¤Þ¤»¤ó¡£");
5793 plog("You may not do that right now.");
5797 /* Hack -- Forget messages */
5802 do_cmd_save_game(FALSE);
5804 Term_key_push(SPECIAL_KEY_QUIT);
5826 /* Require a window */
5835 /* Toggle the "bold" setting */
5836 if (selection == ITEM_BOLD)
5838 /* Toggle the setting */
5839 if (td->font_face & bold)
5841 td->font_face &= ~bold;
5845 td->font_face |= bold;
5848 /* Tile Width Hight Init */
5849 td->tile_wid = td->tile_hgt = 0;
5851 /* Apply and Verify */
5852 term_data_check_font(td);
5853 term_data_check_size(td);
5855 /* Resize and Redraw */
5856 term_data_resize(td);
5857 term_data_redraw(td);
5862 /* Toggle the "wide" setting */
5863 if (selection == ITEM_WIDE)
5865 /* Toggle the setting */
5866 if (td->font_face & extend)
5868 td->font_face &= ~extend;
5872 td->font_face |= extend;
5875 /* Tile Width Hight Init */
5876 td->tile_wid = td->tile_hgt = 0;
5878 /* Apply and Verify */
5879 term_data_check_font(td);
5880 term_data_check_size(td);
5882 /* Resize and Redraw */
5883 term_data_resize(td);
5884 term_data_redraw(td);
5889 /* Get a new font name */
5890 GetMenuItemText(GetMenuHandle(MENU_FONT), selection, s);
5893 /* Save the new font id */
5896 /* Current size is bad for new font */
5897 if (!RealFont(td->font_id, td->font_size))
5899 /* Find similar size */
5900 for (i = 1; i <= 32; i++)
5902 /* Adjust smaller */
5903 if (td->font_size - i >= 8)
5905 if (RealFont(td->font_id, td->font_size - i))
5913 if (td->font_size + i <= 128)
5915 if (RealFont(td->font_id, td->font_size + i))
5924 /* Tile Width Hight Init */
5925 td->tile_wid = td->tile_hgt = 0;
5927 /* Apply and Verify */
5928 term_data_check_font(td);
5929 term_data_check_size(td);
5931 /* Resize and Redraw */
5932 term_data_resize(td);
5933 term_data_redraw(td);
5935 /* Restore the window */
5952 GetMenuItemText(GetMenuHandle(MENU_SIZE), selection, s);
5954 td->font_size = atoi((char*)(s+1));
5956 /* Tile Width Hight Init */
5957 td->tile_wid = td->tile_hgt = 0;
5959 /* Apply and Verify */
5960 term_data_check_font(td);
5961 term_data_check_size(td);
5963 /* Resize and Redraw */
5964 term_data_resize(td);
5965 term_data_redraw(td);
5979 /* Check legality of choice */
5980 if ((i < 0) || (i >= MAX_TERM_DATA)) break;
5982 /* Obtain the window */
5992 td->t->mapped_flag = TRUE;
5994 /* Show the window */
5997 /* Bring to the front */
5998 SelectWindow(td->w);
6010 arg_fiddle = !arg_fiddle;
6016 arg_wizard = !arg_wizard;
6024 /* Sounds submenu */
6029 case ITEM_USE_SOUND:
6031 /* Toggle arg_sound */
6032 arg_sound = !arg_sound;
6034 /* React to changes */
6035 Term_xtra(TERM_XTRA_REACT, 0);
6040 case ITEM_SOUND_SETTING:
6051 /* Graphics submenu */
6058 graf_mode_req = GRAF_MODE_NONE;
6065 graf_mode_req = GRAF_MODE_8X8;
6072 graf_mode_req = GRAF_MODE_16X16;
6080 term_data *td = &data[0];
6082 /* Toggle "arg_bigtile" */
6083 arg_bigtile = !arg_bigtile;
6086 Term_activate(td->t);
6088 /* Resize the term */
6089 Term_resize(td->cols, td->rows);
6098 /* Hack -- Force redraw */
6099 Term_key_push(KTRL('R'));
6104 /* TileWidth submenu */
6105 case SUBMENU_TILEWIDTH:
6116 GetMenuItemText(GetMenuHandle(SUBMENU_TILEWIDTH), selection, s);
6118 td->tile_wid = atoi((char*)(s+1));
6120 /* Apply and Verify */
6121 term_data_check_size(td);
6123 /* Resize and Redraw */
6124 term_data_resize(td);
6125 term_data_redraw(td);
6133 /* TileHeight submenu */
6134 case SUBMENU_TILEHEIGHT:
6145 GetMenuItemText(GetMenuHandle(SUBMENU_TILEHEIGHT), selection, s);
6147 td->tile_hgt = atoi((char*)(s+1));
6149 /* Apply and Verify */
6150 term_data_check_size(td);
6152 /* Resize and Redraw */
6153 term_data_resize(td);
6154 term_data_redraw(td);
6164 /* Clean the menu */
6173 * Check for extra required parameters -- From "Maarten Hazewinkel"
6175 static OSErr CheckRequiredAEParams(const AppleEvent *theAppleEvent)
6178 DescType returnedType;
6181 aeError = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard,
6182 &returnedType, NULL, 0, &actualSize);
6184 if (aeError == errAEDescNotFound) return (noErr);
6186 if (aeError == noErr) return (errAEParamMissed);
6193 * Apple Event Handler -- Open Application
6195 static pascal OSErr AEH_Start(const AppleEvent *theAppleEvent,
6196 AppleEvent *reply, long handlerRefCon)
6198 #pragma unused(reply, handlerRefCon)
6200 return (CheckRequiredAEParams(theAppleEvent));
6205 * Apple Event Handler -- Quit Application
6207 static pascal OSErr AEH_Quit(const AppleEvent *theAppleEvent,
6208 AppleEvent *reply, long handlerRefCon)
6210 #pragma unused(reply, handlerRefCon)
6211 #if TARGET_API_MAC_CARBON
6212 #pragma unused(theAppleEvent)
6214 /* Save the game (if necessary) */
6215 if (game_in_progress && character_generated)
6219 plog("º£¤Ï¥»¡¼¥Ö¤¹¤ë¤³¤È¤Ï½ÐÍè¤Þ¤»¤ó¡£");
6221 plog("You may not do that right now.");
6225 /* Hack -- Forget messages */
6230 do_cmd_save_game(FALSE);
6232 Term_key_push(SPECIAL_KEY_QUIT);
6240 quit_when_ready = TRUE;
6242 /* Check arguments */
6243 return (CheckRequiredAEParams(theAppleEvent));
6249 * Apple Event Handler -- Print Documents
6251 static pascal OSErr AEH_Print(const AppleEvent *theAppleEvent,
6252 AppleEvent *reply, long handlerRefCon)
6254 #pragma unused(theAppleEvent, reply, handlerRefCon)
6256 return (errAEEventNotHandled);
6261 * Apple Event Handler by Steve Linberg (slinberg@crocker.com).
6263 * The old method of opening savefiles from the finder does not work
6264 * on the Power Macintosh, because CountAppFiles and GetAppFiles,
6265 * used to return information about the selected document files when
6266 * an application is launched, are part of the Segment Loader, which
6267 * is not present in the RISC OS due to the new memory architecture.
6269 * The "correct" way to do this is with AppleEvents. The following
6270 * code is modeled on the "Getting Files Selected from the Finder"
6271 * snippet from Think Reference 2.0. (The prior sentence could read
6272 * "shamelessly swiped & hacked")
6274 static pascal OSErr AEH_Open(const AppleEvent *theAppleEvent,
6275 AppleEvent* reply, long handlerRefCon)
6277 #pragma unused(reply, handlerRefCon)
6284 DescType returnedType;
6288 /* Put the direct parameter (a descriptor list) into a docList */
6289 err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &docList);
6290 if (err) return err;
6293 * We ignore the validity check, because we trust the FInder, and we only
6294 * allow one savefile to be opened, so we ignore the depth of the list.
6297 err = AEGetNthPtr(&docList, 1L, typeFSS, &keywd,
6298 &returnedType, (Ptr) &myFSS, sizeof(myFSS), &actualSize);
6299 if (err) return err;
6301 /* Only needed to check savefile type below */
6302 err = FSpGetFInfo(&myFSS, &myFileInfo);
6305 sprintf(foo, "Arg! FSpGetFInfo failed with code %d", err);
6310 /* Ignore non 'SAVE' files */
6311 if (myFileInfo.fdType != 'SAVE') return noErr;
6313 #ifdef MACH_O_CARBON
6315 /* Extract a file name */
6316 (void)spec_to_path(&myFSS, savefile, sizeof(savefile));
6320 /* XXX XXX XXX Extract a file name */
6321 PathNameFromDirID(myFSS.parID, myFSS.vRefNum, (StringPtr)savefile);
6322 pstrcat((StringPtr)savefile, (StringPtr)&myFSS.name);
6324 /* Convert the string */
6325 ptocstr((StringPtr)savefile);
6327 #endif /* MACH_O_CARBON */
6329 /* Delay actual open */
6330 open_when_ready = TRUE;
6333 err = AEDisposeDesc(&docList);
6345 * Macintosh modifiers (event.modifier & ccc):
6346 * cmdKey, optionKey, shiftKey, alphaLock, controlKey
6349 * Macintosh Keycodes (0-63 normal, 64-95 keypad, 96-127 extra):
6394 * Optimize non-blocking calls to "CheckEvents()"
6395 * Idea from "Maarten Hazewinkel <mmhazewi@cs.ruu.nl>"
6397 #define EVENT_TICKS 6
6401 * Check for Events, return TRUE if we process any
6403 * Hack -- Handle AppleEvents if appropriate (ignore result code).
6405 static bool CheckEvents(bool wait)
6421 term_data *td = NULL;
6425 static huge lastTicks = 0L;
6428 /* Access the clock */
6429 curTicks = TickCount();
6431 /* Hack -- Allow efficient checking for non-pending events */
6432 if (!wait && (curTicks < lastTicks + EVENT_TICKS)) return (FALSE);
6434 /* Timestamp last check */
6435 lastTicks = curTicks;
6437 #if TARGET_API_MAC_CARBON
6438 WaitNextEvent( everyEvent, &event, 1L, nil );
6440 /* Let the "system" run */
6443 /* Get an event (or null) */
6444 GetNextEvent(everyEvent, &event);
6447 /* Hack -- Nothing is ready yet */
6448 if (event.what == nullEvent) return (FALSE);
6450 /* Analyze the event */
6458 w = (WindowPtr)event.message;
6469 /* Extract the window */
6470 w = (WindowPtr)event.message;
6472 /* Find the window */
6473 for (i = 0; i < MAX_TERM_DATA; i++)
6475 /* Skip dead windows */
6476 if (!data[i].t) continue;
6478 /* Notice matches */
6479 if (data[i].w == w) td = &data[i];
6482 /* Hack XXX XXX XXX */
6486 /* Redraw the window */
6487 if (td) term_data_redraw(td);
6495 /* Extract some modifiers */
6496 mc = (event.modifiers & controlKey) ? TRUE : FALSE;
6497 ms = (event.modifiers & shiftKey) ? TRUE : FALSE;
6498 mo = (event.modifiers & optionKey) ? TRUE : FALSE;
6499 mx = (event.modifiers & cmdKey) ? TRUE : FALSE;
6501 /* Keypress: (only "valid" if ck < 96) */
6502 ch = (event.message & charCodeMask) & 255;
6504 /* Keycode: see table above */
6505 ck = ((event.message & keyCodeMask) >> 8) & 255;
6507 /* Command + "normal key" -> menu action */
6508 if (mx && (ck < 64))
6510 /* Hack -- Prepare the menus */
6513 /* Run the Menu-Handler */
6516 /* Turn off the menus */
6524 /* Hide the mouse pointer */
6527 /* Normal key -> simple keypress */
6530 /* Enqueue the keypress */
6534 /* Bizarre key -> encoded keypress */
6537 /* Hack -- introduce with control-underscore */
6540 /* Send some modifier keys */
6541 if (mc) Term_keypress('C');
6542 if (ms) Term_keypress('S');
6543 if (mo) Term_keypress('O');
6544 if (mx) Term_keypress('X');
6546 /* Hack -- Downshift and encode the keycode */
6547 Term_keypress('0' + (ck - 64) / 10);
6548 Term_keypress('0' + (ck - 64) % 10);
6550 /* Hack -- Terminate the sequence */
6551 /* MPW can generate 10 or 13 for keycode of '\r' */
6552 /* -noMapCR option swaps '\r' and '\n' */
6553 Term_keypress('\r');
6563 /* Analyze click location */
6564 code = FindWindow(event.where, &w);
6566 /* Find the window */
6567 for (i = 0; i < MAX_TERM_DATA; i++)
6569 /* Skip dead windows */
6570 if (!data[i].t) continue;
6572 /* Notice matches */
6573 if (data[i].w == w) td = &data[i];
6582 menu(MenuSelect(event.where));
6586 #if !TARGET_API_MAC_CARBON
6589 SystemClick(&event, w);
6601 #if TARGET_API_MAC_CARBON
6602 GetQDGlobalsScreenBits( &screen );
6604 screen = qd.screenBits;
6607 r.top += 20; /* GetMBarHeight() XXX XXX XXX */
6608 InsetRect(&r, 4, 4);
6609 DragWindow(w, event.where, &r);
6621 #if TARGET_API_MAC_CARBON
6622 GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &portRect );
6624 portRect = td->w->portRect;
6625 local_to_global( &portRect );
6627 p.h = portRect.left;
6629 #if !TARGET_API_MAC_CARBON
6638 /* Apply and Verify */
6639 term_data_check_size(td);
6649 /* Track the go-away box */
6650 if (TrackGoAway(w, event.where))
6656 td->t->mapped_flag = FALSE;
6658 /* Hide the window */
6672 #if TARGET_API_MAC_CARBON
6673 GetQDGlobalsScreenBits( &screen );
6675 screen = qd.screenBits;
6680 /* Fake rectangle */
6681 r.left = 20 * td->tile_wid + td->size_ow1;
6682 r.right = screen.bounds.right;
6683 r.top = 1 * td->tile_hgt + td->size_oh1;
6684 r.bottom = screen.bounds.bottom;
6686 /* Grow the rectangle */
6687 newsize = GrowWindow(w, event.where, &r);
6690 if (!newsize) break;
6692 /* Extract the new size in pixels */
6693 y = HiWord(newsize) - td->size_oh1 - td->size_oh2;
6694 x = LoWord(newsize) - td->size_ow1 - td->size_ow2;
6696 /* Extract a "close" approximation */
6697 td->rows = y / td->tile_hgt;
6698 td->cols = x / td->tile_wid;
6700 /* Apply and Verify */
6701 term_data_check_size(td);
6703 Term_activate(td->t);
6705 /* Hack -- Resize the term */
6706 Term_resize(td->cols, td->rows);
6708 /* Resize and Redraw */
6709 term_data_resize(td);
6710 term_data_redraw(td);
6729 /* Disk Event -- From "Maarten Hazewinkel" */
6733 #if TARGET_API_MAC_CARBON
6735 /* check for error when mounting the disk */
6736 if (HiWord(event.message) != noErr)
6742 DIBadMount(p, event.message);
6749 /* OS Event -- From "Maarten Hazewinkel" */
6752 switch ((event.message >> 24) & 0x000000FF)
6754 case suspendResumeMessage:
6756 /* Resuming: activate the front window */
6757 if (event.message & resumeFlag)
6759 #if TARGET_API_MAC_CARBON
6762 SetPortWindowPort( FrontWindow() );
6764 GetQDGlobalsArrow( &arrow );
6767 SetPort(FrontWindow());
6768 SetCursor(&qd.arrow);
6772 /* Suspend: deactivate the front window */
6786 /* From "Steve Linberg" and "Maarten Hazewinkel" */
6787 case kHighLevelEvent:
6789 #if TARGET_API_MAC_CARBON
6790 AEProcessAppleEvent(&event);
6792 /* Process apple events */
6793 if (AEProcessAppleEvent(&event) != noErr)
6796 plog("Apple Event Handler¤Î¥¨¥é¡¼¤Ç¤¹.");
6798 plog("Error in Apple Event Handler!");
6802 /* Handle "quit_when_ready" */
6803 if (quit_when_ready)
6806 quit_when_ready = FALSE;
6808 /* Do the menu key */
6811 /* Turn off the menus */
6815 /* Handle "open_when_ready" */
6816 handle_open_when_ready();
6827 /* Something happened */
6834 /*** Some Hooks for various routines ***/
6838 * Mega-Hack -- emergency lifeboat
6840 static vptr lifeboat = NULL;
6844 * Hook to "release" memory
6846 static vptr hook_rnfree(vptr v, huge size)
6849 #pragma unused (size)
6853 /* Alternative method */
6868 * Hook to "allocate" memory
6870 static vptr hook_ralloc(huge size)
6875 /* Make a new pointer */
6876 return (malloc(size));
6880 /* Make a new pointer */
6881 return (NewPtr(size));
6888 * Hook to handle "out of memory" errors
6890 static vptr hook_rpanic(huge size)
6893 #pragma unused (size)
6895 /* vptr mem = NULL; */
6897 /* Free the lifeboat */
6900 /* Free the lifeboat */
6901 DisposePtr(lifeboat);
6903 /* Forget the lifeboat */
6906 /* Mega-Hack -- Warning */
6908 mac_warning("¥á¥â¥ê¡¼¤¬Â¤ê¤Þ¤»¤ó!\rº£¤¹¤°½ªÎ»¤·¤Æ²¼¤µ¤¤!");
6910 mac_warning("Running out of Memory!\rAbort this process now!");
6913 /* Mega-Hack -- Never leave this function */
6914 while (TRUE) CheckEvents(TRUE);
6917 /* Mega-Hack -- Crash */
6923 * Hook to tell the user something important
6925 static void hook_plog(cptr str)
6927 /* Warning message */
6932 * Hook to tell the user something, and then quit
6934 static void hook_quit(cptr str)
6936 /* Warning if needed */
6937 if (str) mac_warning(str);
6939 #ifdef USE_ASYNC_SOUND
6941 /* Clean up sound support */
6944 #endif /* USE_ASYNC_SOUND */
6946 /* Write a preference file */
6954 * Hook to tell the user something, and then crash
6956 static void hook_core(cptr str)
6958 /* XXX Use the debugger */
6959 /* DebugStr(str); */
6962 if (str) mac_warning(str);
6964 /* Warn, then save player */
6966 mac_warning("Ã×̿Ū¤Ê¥¨¥é¡¼¤Ç¤¹.\r¶¯À©Åª¤Ë¥»¡¼¥Ö¤·¤Æ½ªÎ»¤·¤Þ¤¹.");
6968 mac_warning("Fatal error.\rI will now attempt to save and quit.");
6971 /* Attempt to save */
6973 if (!save_player()) mac_warning("·Ù¹ð -- ¥»¡¼¥Ö¤Ë¼ºÇÔ¤·¤Þ¤·¤¿!");
6975 if (!save_player()) mac_warning("Warning -- save failed!");
6984 /*** Main program ***/
6990 * XXX XXX XXX Hack -- This function attempts to "fix" the nasty
6991 * "Macintosh Save Bug" by using "absolute" path names, since on
6992 * System 7 machines anyway, the "current working directory" often
6993 * "changes" due to background processes, invalidating any "relative"
6994 * path names. Note that the Macintosh is limited to 255 character
6995 * path names, so be careful about deeply embedded directories...
6997 * XXX XXX XXX Hack -- This function attempts to "fix" the nasty
6998 * "missing lib folder bug" by allowing the user to help find the
6999 * "lib" folder by hand if the "application folder" code fails...
7001 static void init_stuff(void)
7005 #if !TARGET_API_MAC_CARBON
7022 #if TARGET_API_MAC_CARBON
7024 NavDialogOptions dialogOptions;
7025 FSSpec theFolderSpec;
7026 NavReplyRecord theReply;
7028 /* Fake rectangle */
7035 #if TARGET_API_MAC_CARBON
7036 screenRect = GetQDGlobalsScreenBits(&screen)->bounds;
7038 screenRect = qd.screenBits.bounds;
7040 center_rect(&r, &screenRect);
7042 /* Extract corner */
7047 /* Default to the "lib" folder with the application */
7048 #ifdef MACH_O_CARBON
7049 if (locate_lib(path, sizeof(path)) == NULL) quit(NULL);
7051 refnum_to_name(path, app_dir, app_vol, (char*)("\plib:"));
7055 /* Check until done */
7058 /* Prepare the paths */
7059 init_file_paths(path);
7061 /* Build the filename */
7063 path_build(path, sizeof(path), ANGBAND_DIR_FILE, "news_j.txt");
7065 path_build(path, sizeof(path), ANGBAND_DIR_FILE, "news.txt");
7068 /* Attempt to open and close that file */
7069 if (0 == fd_close(fd_open(path, O_RDONLY))) break;
7073 plog_fmt("'%s' ¥Õ¥¡¥¤¥ë¤ò¥ª¡¼¥×¥ó½ÐÍè¤Þ¤»¤ó.", path);
7075 plog_fmt("Unable to open the '%s' file.", path);
7080 plog("Hengband¤Î'lib'¥Õ¥©¥ë¥À¤¬Â¸ºß¤·¤Ê¤¤¤«Àµ¤·¤¯Ìµ¤¤²ÄǽÀ¤¬¤¢¤ê¤Þ¤¹.");
7082 plog("The Angband 'lib' folder is probably missing or misplaced.");
7087 plog("Please 'open' any file in any sub-folder of the 'lib' folder.");
7089 plog("Please 'open' any file in any sub-folder of the 'lib' folder.");
7092 #if TARGET_API_MAC_CARBON
7093 /* Ask the user to choose the lib folder */
7094 err = NavGetDefaultDialogOptions(&dialogOptions);
7097 if (err != noErr) quit(NULL);
7099 /* Set default location option */
7100 dialogOptions.dialogOptionFlags |= kNavSelectDefaultLocation;
7102 /* Clear preview option */
7103 dialogOptions.dialogOptionFlags &= ~(kNavAllowPreviews);
7105 /* Forbit selection of multiple files */
7106 dialogOptions.dialogOptionFlags &= ~(kNavAllowMultipleFiles);
7108 /* Display location */
7109 dialogOptions.location = topleft;
7111 /* Load the message for the missing folder from the resource fork */
7112 GetIndString(dialogOptions.message, 128, 1);
7114 /* Wait for the user to choose a folder */
7115 err = NavChooseFolder(
7123 /* Assume the player doesn't want to go on */
7124 if ((err != noErr) || !theReply.validRecord) quit(NULL);
7126 /* Retrieve FSSpec from the reply */
7128 AEKeyword theKeyword;
7129 DescType actualType;
7132 /* Get a pointer to selected folder */
7134 &(theReply.selection),
7144 if (err != noErr) quit(NULL);
7147 /* Free navitagor reply */
7148 err = NavDisposeReply(&theReply);
7151 if (err != noErr) quit(NULL);
7153 /* Extract textual file name for given file */
7156 theFolderSpec.parID,
7157 theFolderSpec.vRefNum,
7158 (char *)theFolderSpec.name);
7160 /* Allow "text" files */
7163 /* Allow "save" files */
7166 /* Allow "data" files */
7170 SFGetFile(topleft, "\p", NULL, 3, types, NULL, &reply);
7173 if (!reply.good) quit(NULL);
7175 /* Extract textual file name for given file */
7176 GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
7177 refnum_to_name(path, drefnum, vrefnum, (char*)reply.fName);
7180 /* Hack -- Remove the "filename" */
7181 i = strlen(path) - 1;
7182 while ((i > 0) && (path[i] != ':')) i--;
7183 if (path[i] == ':') path[i+1] = '\0';
7185 /* Hack -- allow "lib" folders */
7186 if (suffix(path, "lib:")) continue;
7188 /* Hack -- Remove the "sub-folder" */
7190 while ((i > 1) && (path[i] != ':')) i--;
7191 if (path[i] == ':') path[i+1] = '\0';
7197 * Macintosh Main loop
7201 EventRecord tempEvent;
7202 int numberOfMasters = 10;
7204 #if !TARGET_API_MAC_CARBON
7205 /* Increase stack space by 64K */
7206 SetApplLimit(GetApplLimit() - 131072L);//65536L);
7208 /* Stretch out the heap to full size */
7212 /* Get more Masters */
7213 while (numberOfMasters--) MoreMasters();
7215 #if !TARGET_API_MAC_CARBON
7216 /* Set up the Macintosh */
7217 InitGraf(&qd.thePort);
7231 FlushEvents(everyEvent, 0);
7233 /* Flush events some more (?) */
7234 (void)EventAvail(everyEvent, &tempEvent);
7235 (void)EventAvail(everyEvent, &tempEvent);
7236 (void)EventAvail(everyEvent, &tempEvent);
7239 #ifdef ANGBAND_LITE_MAC
7243 #else /* ANGBAND_LITE_MAC */
7245 # if defined(powerc) || defined(__powerc)
7247 /* Assume System 7 */
7249 /* Assume Color Quickdraw */
7253 #if TARGET_API_MAC_CARBON
7259 /* Check for existence of Carbon */
7260 err = Gestalt(gestaltCarbonVersion, &response);
7262 if (err != noErr) quit("This program requires Carbon API");
7272 /* Check the Gestalt */
7273 err = Gestalt(gestaltSystemVersion, &versionNumber);
7275 /* Check the version */
7276 if ((err != noErr) || (versionNumber < 0x0700))
7279 quit("¤³¤Î¥×¥í¥°¥é¥à¤Ï´Á»úTalk7.x.x°Ê¹ß¤ÇÆ°ºî¤·¤Þ¤¹.");
7281 quit("You must have System 7 to use this program.");
7291 /* Check the environs */
7292 if (SysEnvirons(1, &env) != noErr)
7295 quit("SysEnvirons ¥³¡¼¥ë¤Ï¼ºÇÔ¤·¤Þ¤·¤¿¡ª");
7297 quit("The SysEnvirons call failed!");
7301 /* Check for System Seven Stuff */
7302 if (env.systemVersion < 0x0700)
7305 quit("¤³¤Î¥×¥í¥°¥é¥à¤Ï´Á»úTalk7.x.x°Ê¹ß¤ÇÆ°ºî¤·¤Þ¤¹.");
7307 quit("You must have System 7 to use this program.");
7311 /* Check for Color Quickdraw */
7312 if (!env.hasColorQD)
7315 quit("¤³¤Î¥×¥í¥°¥é¥à¤ÏColor Quickdraw¤¬Ìµ¤¤¤ÈÆ°ºî¤·¤Þ¤»¤ó.");
7317 quit("You must have Color Quickdraw to use this program.");
7325 #endif /* ANGBAND_LITE_MAC */
7328 * Remember Mac OS version, in case we have to cope with version-specific
7331 (void)Gestalt(gestaltSystemVersion, &mac_os_version);
7334 /* Obtain a "Universal Procedure Pointer" */
7335 AEH_Start_UPP = NewAEEventHandlerUPP(AEH_Start);
7336 /* Install the hook (ignore error codes) */
7337 AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, AEH_Start_UPP,
7340 /* Obtain a "Universal Procedure Pointer" */
7341 AEH_Quit_UPP = NewAEEventHandlerUPP(AEH_Quit);
7342 /* Install the hook (ignore error codes) */
7343 AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, AEH_Quit_UPP,
7346 /* Obtain a "Universal Procedure Pointer" */
7347 AEH_Print_UPP = NewAEEventHandlerUPP(AEH_Print);
7348 /* Install the hook (ignore error codes) */
7349 AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, AEH_Print_UPP,
7352 /* Obtain a "Universal Procedure Pointer" */
7353 AEH_Open_UPP = NewAEEventHandlerUPP(AEH_Open);
7354 /* Install the hook (ignore error codes) */
7355 AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, AEH_Open_UPP,
7359 #ifndef MACH_O_CARBON
7360 /* Find the current application */
7364 /* Mark ourself as the file creator */
7365 _fcreator = ANGBAND_CREATOR;
7367 /* Default to saving a "text" file */
7371 #if defined(__MWERKS__)
7373 /* Obtian a "Universal Procedure Pointer" */
7374 #if TARGET_API_MAC_CARBON
7375 ynfilterUPP = NewModalFilterUPP(ynfilter);
7377 ynfilterUPP = NewModalFilterProc(ynfilter);
7383 /* Hook in some "z-virt.c" hooks */
7384 rnfree_aux = hook_rnfree;
7385 ralloc_aux = hook_ralloc;
7386 rpanic_aux = hook_rpanic;
7388 /* Hooks in some "z-util.c" hooks */
7389 plog_aux = hook_plog;
7390 quit_aux = hook_quit;
7391 core_aux = hook_core;
7393 BackColor(blackColor);
7394 ForeColor(whiteColor);
7396 /* Show the "watch" cursor */
7397 SetCursor(*(GetCursor(watchCursor)));
7399 /* Prepare the menubar */
7402 /* Prepare the windows */
7405 #ifndef MACH_O_CARBON
7413 /* Hack -- process all events */
7414 while (CheckEvents(TRUE)) /* loop */;
7416 /* Reset the cursor */
7417 #if TARGET_API_MAC_CARBON
7420 GetQDGlobalsArrow( &arrow );
7424 SetCursor( &qd.arrow );
7428 /* Mega-Hack -- Allocate a "lifeboat" */
7429 lifeboat = NewPtr(16384);
7433 /* Load sound effect resources */
7436 #endif /* USE_QT_SOUND */
7438 /* Note the "system" */
7439 ANGBAND_SYS = "mac";
7444 /* Catch nasty signals */
7451 /* Hack -- process all events */
7452 while (CheckEvents(TRUE)) /* loop */;
7455 /* We are now initialized */
7459 /* Handle "open_when_ready" */
7460 handle_open_when_ready();
7466 /* Prompt the user */
7468 prt("'¥Õ¥¡¥¤¥ë'¥á¥Ë¥å¡¼¤è¤ê'¿·µ¬'¤Þ¤¿¤Ï'³«¤¯...'¤òÁªÂò¤·¤Æ¤¯¤À¤µ¤¤¡£", 23, 10);
7470 prt("[Choose 'New' or 'Open' from the 'File' menu]", 23, 15);
7473 /* Flush the prompt */
7477 /* Hack -- Process Events Forever */
7478 while (TRUE) CheckEvents(TRUE);