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 <QuickDraw.h>
145 #include <Palettes.h>
146 #include <StandardFile.h>
147 #include <DiskInit.h>
148 #include <ToolUtils.h>
151 #include <Resources.h>
152 #include <Controls.h>
155 #include <QDOffscreen.h>
157 #if TARGET_API_MAC_CARBON
158 #include <Navigation.h>
159 #include <CFPreferences.h>
160 #include <CFNumber.h>
162 # include <CarbonStdCLib.h>
173 * Cleaning up a couple of things to make these easier to change --AR
176 #define PREF_FILE_NAME "Hengband Preferences"
178 #define PREF_FILE_NAME "Hengband-E Preferences"
182 * Use "malloc()" instead of "NewPtr()"
184 /* #define USE_MALLOC */
187 #if defined(powerc) || defined(__powerc)
190 * Disable "LITE" version
192 # undef ANGBAND_LITE_MAC
197 #ifdef ANGBAND_LITE_MAC
200 * Maximum number of windows
202 # define MAX_TERM_DATA 1
204 #else /* ANGBAND_LITE_MAC */
207 * Maximum number of windows
209 # define MAX_TERM_DATA 8
212 * Activate some special code
214 # define USE_SFL_CODE
216 #endif /* ANGBAND_LITE_MAC */
223 * Include the necessary header files
225 #include <AppleEvents.h>
233 * Globals for MPW compilation
235 #if defined(MACH_O_CARBON) || defined(MAC_MPW)
237 #if !TARGET_API_MAC_CARBON
249 * The Angband Color Set (0 to 15):
250 * Black, White, Slate, Orange, Red, Blue, Green, Umber
251 * D-Gray, L-Gray, Violet, Yellow, L-Red, L-Blue, L-Green, L-Umber
253 * Colors 8 to 15 are basically "enhanced" versions of Colors 0 to 7.
255 * On the Macintosh, we use color quickdraw, and we use actual "RGB"
256 * values below to choose the 16 colors.
258 * If we are compiled for ancient machines, we bypass color and simply
259 * draw everything in white (letting "z-term.c" automatically convert
260 * "black" into "wipe" calls).
262 static RGBColor foo[16] =
264 {0x0000, 0x0000, 0x0000}, /* TERM_DARK */
265 {0xFFFF, 0xFFFF, 0xFFFF}, /* TERM_WHITE */
266 {0x8080, 0x8080, 0x8080}, /* TERM_SLATE */
267 {0xFFFF, 0x8080, 0x0000}, /* TERM_ORANGE */
268 {0xC0C0, 0x0000, 0x0000}, /* TERM_RED */
269 {0x0000, 0x8080, 0x4040}, /* TERM_GREEN */
270 {0x0000, 0x0000, 0xFFFF}, /* TERM_BLUE */
271 {0x8080, 0x4040, 0x0000}, /* TERM_UMBER */
272 {0x4040, 0x4040, 0x4040}, /* TERM_L_DARK */
273 {0xC0C0, 0xC0C0, 0xC0C0}, /* TERM_L_WHITE */
274 {0xFFFF, 0x0000, 0xFFFF}, /* TERM_VIOLET */
275 {0xFFFF, 0xFFFF, 0x0000}, /* TERM_YELLOW */
276 {0xFFFF, 0x0000, 0x0000}, /* TERM_L_RED */
277 {0x0000, 0xFFFF, 0x0000}, /* TERM_L_GREEN */
278 {0x0000, 0xFFFF, 0xFFFF}, /* TERM_L_BLUE */
279 {0xC0C0, 0x8080, 0x4040} /* TERM_L_UMBER */
288 typedef struct term_data term_data;
301 #ifdef ANGBAND_LITE_MAC
305 #else /* ANGBAND_LITE_MAC */
317 #endif /* ANGBAND_LITE_MAC */
360 * Forward declare -- see below
362 static bool CheckEvents(bool wait);
366 * Hack -- location of the main directory
368 static short app_vol;
373 * Delay handling of double-clicked savefiles
375 Boolean open_when_ready = FALSE;
378 * Delay handling of pre-emptive "quit" event
380 Boolean quit_when_ready = FALSE;
384 * Hack -- game in progress
386 static int game_in_progress = 0;
390 * Only do "SetPort()" when needed
392 static WindowPtr active = NULL;
397 * An array of term_data's
399 static term_data data[MAX_TERM_DATA];
404 * Note when "open"/"new" become valid
406 static bool initialized = FALSE;
409 * Version of Mac OS - for version specific bug workarounds (; ;)
411 static long mac_os_version;
415 * CodeWarrior uses Universal Procedure Pointers
417 static ModalFilterUPP ynfilterUPP;
424 AEEventHandlerUPP AEH_Start_UPP;
425 AEEventHandlerUPP AEH_Quit_UPP;
426 AEEventHandlerUPP AEH_Print_UPP;
427 AEEventHandlerUPP AEH_Open_UPP;
435 static int ext_sound = 0;
443 #define SND_CMD_ERROR 6
445 static int soundchoice[] = {
513 static short soundmode[8];
515 static int ext_graf = 0;
520 * Convert refnum+vrefnum+fname into a full file name
521 * Store this filename in 'buf' (make sure it is long enough)
522 * Note that 'fname' looks to be a "pascal" string
524 #if TARGET_API_MAC_CARBON
525 static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname)
541 for (j=1; j<=fname[0]; j++)
543 res[i-fname[0]+j] = fname[j];
552 pb.dirInfo.ioDrDirID=pb.dirInfo.ioDrParID;
553 err = FSMakeFSSpec( vref, dirID, "\p", &spec );
559 for (j=1; j<=spec.name[0]; j++)
561 res[i-spec.name[0]+j] = spec.name[j];
568 /* Extract the result */
569 for (j = 0, i++; res[i]; j++, i++) buf[j] = res[i];
573 static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname)
585 for (j=1; j<=fname[0]; j++)
587 res[i-fname[0]+j] = fname[j];
591 pb.ioCompletion=NULL;
593 pb.ioVRefNum=vrefnum;
599 pb.ioDrDirID=pb.ioDrParID;
600 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
602 for (j=1; j<=name[0]; j++)
604 res[i-name[0]+j] = name[j];
608 if (pb.ioDrDirID == fsRtDirID) break;
611 /* Extract the result */
612 for (j = 0, i++; res[i]; j++, i++) buf[j] = res[i];
617 #if TARGET_API_MAC_CARBON
618 pascal OSErr FSpLocationFromFullPath(short fullPathLength,
619 const void *fullPath,
627 /* Create a minimal alias from the full pathname */
628 nullString[0] = 0; /* null string to indicate no zone or server name */
629 result = NewAliasMinimalFromFullPath(fullPathLength, fullPath, nullString, nullString, &alias);
630 if ( result == noErr )
632 /* Let the Alias Manager resolve the alias. */
633 result = ResolveAlias(NULL, alias, spec, &wasChanged);
635 /* work around Alias Mgr sloppy volume matching bug */
636 if ( spec->vRefNum == 0 )
638 /* invalidate wrong FSSpec */
643 DisposeHandle((Handle)alias); /* Free up memory used */
652 * XXX XXX XXX Allow the system to ask us for a filename
654 static bool askfor_file(char *buf, int len)
662 /* Default file name */
663 sprintf((char*)dflt + 1, "%s's description", buf);
664 dflt[0] = strlen((char*)dflt + 1);
666 /* Ask for a file name */
667 topleft.h=(qd.screenBits.bounds.left+qd.screenBits.bounds.right)/2-344/2;
668 topleft.v=(2*qd.screenBits.bounds.top+qd.screenBits.bounds.bottom)/3-188/2;
669 SFPutFile(topleft, "\pSelect a filename:", dflt, NULL, &reply);
670 /* StandardPutFile("\pSelect a filename:", dflt, &reply); */
678 GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
680 /* Extract the name */
681 refnum_to_name(buf, drefnum, vrefnum, (char*)reply.fName);
693 static void local_to_global( Rect *r )
700 LocalToGlobal( &temp );
708 LocalToGlobal( &temp );
714 static void global_to_local( Rect *r )
721 GlobalToLocal( &temp );
729 GlobalToLocal( &temp );
739 * Convert pathname to an appropriate format, because MPW's
740 * CarbonStdCLib chose to use system's native path format,
741 * making our lives harder to create binaries that run on
742 * OS 8/9 and OS X :( -- pelpel
744 void convert_pathname(char* path)
748 /* Nothing has to be done for CarbonLib on Classic */
749 if (mac_os_version >= 0x1000)
751 /* Convert to POSIX style */
752 ConvertHFSPathToUnixPath(path, buf);
754 /* Copy the result back */
762 # ifdef CHECK_MODIFICATION_TIME
765 * Although there is no easy way to emulate fstat in the old interface,
766 * we still can do stat-like things, because Mac OS is an OS.
768 static int get_modification_time(cptr path, u32b *mod_time)
774 /* Paranoia - make sure the pathname fits in Str255 */
776 if (i > 255) return (-1);
778 /* Convert pathname to a Pascal string */
779 strncpy((char *)pathname + 1, path, 255);
782 /* Set up parameter block */
783 pb.hFileInfo.ioNamePtr = pathname;
784 pb.hFileInfo.ioFDirIndex = 0;
785 pb.hFileInfo.ioVRefNum = app_vol;
786 pb.hFileInfo.ioDirID = 0;
788 /* Get catalog information of the file */
789 if (PBGetCatInfoSync(&pb) != noErr) return (-1);
791 /* Set modification date and time */
792 *mod_time = pb.hFileInfo.ioFlMdDat;
800 * A (non-Mach-O) Mac OS version of check_modification_time, for those
801 * compilers without good enough POSIX-compatibility libraries XXX XXX
803 errr check_modification_date(int fd, cptr template_file)
806 u32b txt_stat, raw_stat;
811 /* Build the file name */
812 path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, template_file);
815 convert_pathname(buf);
817 /* Obtain modification time */
818 if (get_modification_time(buf, &txt_stat)) return (-1);
820 /* XXX Build filename of the corresponding *.raw file */
821 strnfmt(fname, sizeof(fname), "%s", template_file);
824 p = strrchr(fname, '.');
827 if (p == NULL) return (-1);
829 /* Substitute ".raw" for ".txt" */
832 /* Build the file name of the raw file */
833 path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, fname);
836 convert_pathname(buf);
838 /* Obtain modification time */
839 if (get_modification_time(buf, &raw_stat)) return (-1);
841 /* Ensure the text file is not newer than the raw file */
842 if (txt_stat > raw_stat) return (-1);
844 /* Keep using the current .raw file */
848 # endif /* CHECK_MODIFICATION_TIME */
853 * Center a rectangle inside another rectangle
855 static void center_rect(Rect *r, Rect *s)
857 int centerx = (s->left + s->right)/2;
858 int centery = (2*s->top + s->bottom)/3;
859 int dx = centerx - (r->right - r->left)/2 - r->left;
860 int dy = centery - (r->bottom - r->top)/2 - r->top;
869 * Convert a pascal string in place
871 * This function may be defined elsewhere, but since it is so
872 * small, it is not worth finding the proper function name for
873 * all the different platforms.
875 static void ptocstr(StringPtr src)
879 /* Hack -- pointer */
880 char *s = (char*)(src);
882 /* Hack -- convert the string */
883 for (i = s[0]; i; i--, s++) s[0] = s[1];
885 /* Hack -- terminate the string */
890 #if defined(USE_SFL_CODE)
894 * The following three routines (pstrcat, pstrinsert, and PathNameFromDirID)
895 * were taken from the Think Reference section called "Getting a Full Pathname"
896 * (under the File Manager section). We need PathNameFromDirID to get the
897 * full pathname of the opened savefile, making no assumptions about where it
900 * I had to hack PathNameFromDirID a little for MetroWerks, but it's awfully
903 static void pstrcat(StringPtr dst, StringPtr src)
906 BlockMove(src + 1, dst + *dst + 1, *src);
908 /* adjust length byte */
913 * pstrinsert - insert string 'src' at beginning of string 'dst'
915 static void pstrinsert(StringPtr dst, StringPtr src)
917 /* make room for new string */
918 BlockMove(dst + 1, dst + *src + 1, *dst);
920 /* copy new string in */
921 BlockMove(src + 1, dst + 1, *src);
923 /* adjust length byte */
927 static void PathNameFromDirID(long dirID, short vRefNum, StringPtr fullPathName)
930 Str255 directoryName;
933 fullPathName[0] = '\0';
935 block.dirInfo.ioDrParID = dirID;
936 block.dirInfo.ioNamePtr = directoryName;
940 block.dirInfo.ioVRefNum = vRefNum;
941 block.dirInfo.ioFDirIndex = -1;
942 block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID;
943 err = PBGetCatInfo(&block, FALSE);
944 pstrcat(directoryName, (StringPtr)"\p:");
945 pstrinsert(fullPathName, directoryName);
946 if (block.dirInfo.ioDrDirID == 2) break;
952 #if TARGET_API_MAC_CARBON
954 static OSErr ChooseFile( StringPtr filename, FSSpec selfld )
956 NavReplyRecord reply;
957 NavDialogOptions dialogOptions;
958 NavTypeListHandle navTypeList = NULL;
962 AECreateDesc( typeFSS, &selfld, sizeof(FSSpec), &deffld );
964 err = NavGetDefaultDialogOptions( &dialogOptions );
968 err = NavChooseFile( &deffld, &reply, &dialogOptions, NULL, NULL, NULL, navTypeList, NULL );
970 if ( reply.validRecord && err == noErr ){
971 // grab the target FSSpec from the AEDesc:
977 // retrieve the returned selection:
978 // there is only one selection here we get only the first AEDescList:
979 if (( err = AEGetNthPtr( &(reply.selection), 1, typeFSS, &keyWord, &typeCode, &finalFSSpec, sizeof( FSSpec ), &actualSize )) == noErr )
981 refnum_to_name( (char *)filename, finalFSSpec.parID, finalFSSpec.vRefNum, (char *)finalFSSpec.name );
982 // 'finalFSSpec' is the chosen file¥Î
985 err = NavDisposeReply( &reply );
987 if( navTypeList != NULL )
989 DisposeHandle( (Handle)navTypeList );
994 AEDisposeDesc( &deffld );
1002 * Activate a given window, if necessary
1004 static void activate(WindowPtr w)
1010 #if TARGET_API_MAC_CARBON
1011 if (w) SetPortWindowPort(w);
1023 * Display a warning message
1025 static void mac_warning(cptr warning)
1030 /* Limit of 250 chars */
1031 len = strlen(warning);
1032 if (len > 250) len = 250;
1034 /* Make a "Pascal" string */
1036 for (i=0; i<len; i++) text[i+1] = warning[i];
1038 /* Prepare the dialog box values */
1039 ParamText(text, "\p", "\p", "\p");
1041 /* Display the Alert, wait for Okay */
1047 /*** Some generic functions ***/
1050 #ifdef ANGBAND_LITE_MAC
1053 * Hack -- activate a color (0 to 255)
1055 #define term_data_color(TD,A) /* Nothing */
1057 #else /* ANGBAND_LITE_MAC */
1060 * Hack -- activate a color (0 to 255)
1062 static void term_data_color(term_data *td, int a)
1068 /* Extract the R,G,B data */
1069 rv = angband_color_table[a][1];
1070 gv = angband_color_table[a][2];
1071 bv = angband_color_table[a][3];
1074 color.red = (rv | (rv << 8));
1075 color.green = (gv | (gv << 8));
1076 color.blue = (bv | (bv << 8));
1078 /* Activate the color */
1079 RGBForeColor(&color);
1081 /* Memorize color */
1085 #endif /* ANGBAND_LITE_MAC */
1089 * Hack -- Apply and Verify the "font" info
1091 * This should usually be followed by "term_data_check_size()"
1093 static void term_data_check_font(term_data *td)
1099 WindowPtr old = active;
1105 /* Instantiate font */
1106 TextFont(td->font_id);
1107 TextSize(td->font_size);
1108 TextFace(td->font_face);
1110 /* Extract the font info */
1113 /* Assume monospaced */
1114 td->font_mono = TRUE;
1116 /* Extract the font sizing values XXX XXX XXX */
1117 td->font_wid = CharWidth('@'); /* info.widMax; */
1118 td->font_hgt = info.ascent + info.descent;
1120 td->font_o_y = info.ascent;
1122 /* Check important characters */
1123 for (i = 33; i < 127; i++)
1125 /* Hack -- notice non-mono-space */
1126 if (td->font_wid != CharWidth(i)) td->font_mono = FALSE;
1128 /* Hack -- collect largest width */
1129 if (td->font_wid < CharWidth(i)) td->font_wid = CharWidth(i);
1132 /* Set default offsets */
1133 td->tile_o_x = td->font_o_x;
1134 td->tile_o_y = td->font_o_y;
1136 /* Set default tile size */
1137 if( td->tile_wid == 0 && td->tile_hgt == 0 ){
1138 td->tile_wid = td->font_wid;
1139 td->tile_hgt = td->font_hgt;
1142 /* Re-activate the old window */
1148 * Hack -- Apply and Verify the "size" info
1150 static void term_data_check_size(term_data *td)
1154 #if TARGET_API_MAC_CARBON
1155 GetQDGlobalsScreenBits( &screen );
1157 screen = qd.screenBits;
1159 /* Minimal window size */
1162 /* Enforce minimal size */
1163 if (td->cols < 80) td->cols = 80;
1164 if (td->rows < 24) td->rows = 24;
1167 /* Allow small windows for the rest */
1170 if (td->cols < 1) td->cols = 1;
1171 if (td->rows < 1) td->rows = 1;
1174 /* Minimal tile size */
1175 if (td->tile_wid < 4) td->tile_wid = 4;
1176 if (td->tile_hgt < 4) td->tile_hgt = 4;
1178 /* Default tile offsets */
1179 td->tile_o_x = (td->tile_wid - td->font_wid) / 2;
1180 td->tile_o_y = (td->tile_hgt - td->font_hgt) / 2;
1182 /* Minimal tile offsets */
1183 if (td->tile_o_x < 0) td->tile_o_x = 0;
1184 if (td->tile_o_y < 0) td->tile_o_y = 0;
1186 /* Apply font offsets */
1187 td->tile_o_x += td->font_o_x;
1188 td->tile_o_y += td->font_o_y;
1190 /* Calculate full window size */
1191 td->size_wid = td->cols * td->tile_wid + td->size_ow1 + td->size_ow2;
1192 td->size_hgt = td->rows * td->tile_hgt + td->size_oh1 + td->size_oh2;
1194 /* Verify the top */
1195 if (td->r.top > screen.bounds.bottom - td->size_hgt)
1197 td->r.top = screen.bounds.bottom - td->size_hgt;
1200 /* Verify the top */
1201 if (td->r.top < screen.bounds.top + 30)
1203 td->r.top = screen.bounds.top + 30;
1206 /* Verify the left */
1207 if (td->r.left > screen.bounds.right - td->size_wid)
1209 td->r.left = screen.bounds.right - td->size_wid;
1212 /* Verify the left */
1213 if (td->r.left < screen.bounds.left)
1215 td->r.left = screen.bounds.left;
1218 /* Calculate bottom right corner */
1219 td->r.right = td->r.left + td->size_wid;
1220 td->r.bottom = td->r.top + td->size_hgt;
1222 /* Assume no graphics */
1223 td->t->higher_pict = FALSE;
1224 td->t->always_pict = FALSE;
1226 #ifdef ANGBAND_LITE_MAC
1230 #else /* ANGBAND_LITE_MAC */
1232 /* Handle graphics */
1235 /* Use higher_pict whenever possible */
1236 if (td->font_mono) td->t->higher_pict = TRUE;
1238 /* Use always_pict only when necessary */
1239 else td->t->always_pict = TRUE;
1242 #endif /* ANGBAND_LITE_MAC */
1244 /* Fake mono-space */
1245 if (!td->font_mono ||
1246 (td->font_wid != td->tile_wid) ||
1247 (td->font_hgt != td->tile_hgt))
1249 /* Handle fake monospace -- this is SLOW */
1250 if (td->t->higher_pict) td->t->higher_pict = FALSE;
1251 td->t->always_pict = TRUE;
1256 * Hack -- resize a term_data
1258 * This should normally be followed by "term_data_resize()"
1260 static void term_data_resize(term_data *td)
1262 /* Actually resize the window */
1263 SizeWindow(td->w, td->size_wid, td->size_hgt, 0);
1269 * Hack -- redraw a term_data
1271 * Note that "Term_redraw()" calls "TERM_XTRA_CLEAR"
1273 static void term_data_redraw(term_data *td)
1277 /* Activate the term */
1278 Term_activate(td->t);
1280 /* Redraw the contents */
1283 /* Flush the output */
1286 /* Restore the old term */
1289 /* No need to redraw */
1290 #if TARGET_API_MAC_CARBON
1292 RgnHandle theRgn = NewRgn();
1293 GetWindowRegion( td->w, kWindowContentRgn, theRgn );
1294 ValidWindowRgn( (WindowRef)(td->w), theRgn );
1295 DisposeRgn( theRgn );
1298 ValidRect(&td->w->portRect);
1306 #ifdef ANGBAND_LITE_MAC
1310 #else /* ANGBAND_LITE_MAC */
1317 static int pictID = 1001; /* 8x8 tiles; 16x16 tiles are 1002 */
1319 static int grafWidth = 8; /* Always equal to grafHeight */
1320 static int grafHeight = 8; /* Either 8 or 16 */
1322 static bool arg_newstyle_graphics;
1323 static bool use_newstyle_graphics;
1328 typedef struct FrameRec FrameRec;
1333 * - GWorld for the frame image
1334 * - Handle to pix map (saved for unlocking/locking)
1335 * - Pointer to color pix map (valid only while locked)
1339 GWorldPtr framePort;
1340 PixMapHandle framePixHndl;
1347 * The global picture data
1349 static FrameRec *frameP = NULL;
1355 static void BenSWLockFrame(FrameRec *srcFrameP)
1357 PixMapHandle pixMapH;
1359 pixMapH = GetGWorldPixMap(srcFrameP->framePort);
1360 (void)LockPixels(pixMapH);
1361 HLockHi((Handle)pixMapH);
1362 srcFrameP->framePixHndl = pixMapH;
1363 #if TARGET_API_MAC_CARBON
1364 srcFrameP->framePix = (PixMapPtr)*(Handle)pixMapH;
1366 srcFrameP->framePix = (PixMapPtr)StripAddress(*(Handle)pixMapH);
1375 static void BenSWUnlockFrame(FrameRec *srcFrameP)
1377 if (srcFrameP->framePort != NULL)
1379 HUnlock((Handle)srcFrameP->framePixHndl);
1380 UnlockPixels(srcFrameP->framePixHndl);
1383 srcFrameP->framePix = NULL;
1387 static OSErr BenSWCreateGWorldFromPict(
1388 GWorldPtr *pictGWorld,
1392 GWorldPtr saveGWorld;
1393 GDHandle saveGDevice;
1394 GWorldPtr tempGWorld;
1403 depth = data[0].pixelDepth;
1406 theGDH = data[0].theGDH;
1408 /* Obtain size rectangle */
1409 pictRect = (**pictH).picFrame;
1410 OffsetRect(&pictRect, -pictRect.left, -pictRect.top);
1412 /* Create a GWorld */
1413 err = NewGWorld(&tempGWorld, depth, &pictRect, nil,
1414 theGDH, noNewDevice);
1423 *pictGWorld = tempGWorld;
1426 GetGWorld(&saveGWorld, &saveGDevice);
1429 SetGWorld(tempGWorld, nil);
1431 /* Dump the pict into the GWorld */
1432 (void)LockPixels(GetGWorldPixMap(tempGWorld));
1433 EraseRect(&pictRect);
1434 DrawPicture(pictH, &pictRect);
1435 UnlockPixels(GetGWorldPixMap(tempGWorld));
1437 /* Restore GWorld */
1438 SetGWorld(saveGWorld, saveGDevice);
1448 * Init the global "frameP"
1451 static errr globe_init(void)
1455 GWorldPtr tempPictGWorldP;
1459 /* Use window XXX XXX XXX */
1460 #if TARGET_API_MAC_CARBON
1461 SetPortWindowPort(data[0].w);
1467 /* Get the pict resource */
1468 newPictH = GetPicture(pictID);
1470 /* Analyze result */
1471 err = (newPictH ? 0 : -1);
1478 err = BenSWCreateGWorldFromPict(&tempPictGWorldP, newPictH);
1480 /* Release resource */
1481 ReleaseResource((Handle)newPictH);
1486 /* Create the frame */
1487 frameP = (FrameRec*)NewPtrClear((Size)sizeof(FrameRec));
1489 /* Analyze result */
1490 err = (frameP ? 0 : -1);
1496 frameP->framePort = tempPictGWorldP;
1499 BenSWLockFrame(frameP);
1510 * Nuke the global "frameP"
1512 static errr globe_nuke(void)
1518 BenSWUnlockFrame(frameP);
1520 /* Dispose of the GWorld */
1521 DisposeGWorld(frameP->framePort);
1523 /* Dispose of the memory */
1524 DisposePtr((Ptr)frameP);
1531 FlushEvents(everyEvent, 0);
1538 #endif /* ANGBAND_LITE_MAC */
1542 /*** Support for the "z-term.c" package ***/
1546 * Initialize a new Term
1548 * Note also the "window type" called "noGrowDocProc", which might be more
1549 * appropriate for the main "screen" window.
1551 * Note the use of "srcCopy" mode for optimized screen writes.
1553 static void Term_init_mac(term *t)
1555 term_data *td = (term_data*)(t->data);
1557 static RGBColor black = {0x0000,0x0000,0x0000};
1558 static RGBColor white = {0xFFFF,0xFFFF,0xFFFF};
1560 #ifdef ANGBAND_LITE_MAC
1562 /* Make the window */
1563 td->w = NewWindow(0, &td->r, td->title, 0, noGrowDocProc, (WindowPtr)-1, 1, 0L);
1565 #else /* ANGBAND_LITE_MAC */
1567 /* Make the window */
1568 td->w = NewCWindow(0, &td->r, td->title, 0, documentProc, (WindowPtr)-1, 1, 0L);
1570 #endif /* ANGBAND_LITE_MAC */
1572 /* Activate the window */
1575 /* Erase behind words */
1578 /* Apply and Verify */
1579 term_data_check_font(td);
1580 term_data_check_size(td);
1582 /* Resize the window */
1583 term_data_resize(td);
1585 #ifdef ANGBAND_LITE_MAC
1587 /* Prepare the colors (base colors) */
1588 BackColor(blackColor);
1589 ForeColor(whiteColor);
1591 #else /* ANGBAND_LITE_MAC */
1593 /* Prepare the colors (real colors) */
1594 RGBBackColor(&black);
1595 RGBForeColor(&white);
1602 GDHandle currentGDH;
1603 GWorldPtr windowGWorld;
1604 PixMapHandle basePixMap;
1606 /* Obtain the rect */
1607 #if TARGET_API_MAC_CARBON
1608 GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &globalRect );
1610 globalRect = td->w->portRect;
1611 LocalToGlobal((Point*)&globalRect.top);
1612 LocalToGlobal((Point*)&globalRect.bottom);
1615 /* Obtain the proper GDH */
1616 mainGDH = GetMaxDevice(&globalRect);
1618 /* Extract GWorld and GDH */
1619 GetGWorld(&windowGWorld, ¤tGDH);
1621 /* Obtain base pixmap */
1622 basePixMap = (**mainGDH).gdPMap;
1624 /* Save pixel depth */
1625 td->pixelDepth = (**basePixMap).pixelSize;
1627 /* Save Window GWorld */
1628 td->theGWorld = windowGWorld;
1630 /* Save Window GDH */
1631 td->theGDH = currentGDH;
1634 td->mainSWGDH = mainGDH;
1637 #endif /* ANGBAND_LITE_MAC */
1642 #if TARGET_API_MAC_CARBON
1643 GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &portRect );
1644 global_to_local( &portRect );
1646 portRect = td->w->portRect;
1648 /* Clip to the window */
1649 ClipRect(&portRect);
1651 /* Erase the window */
1652 EraseRect(&portRect);
1654 /* Invalidate the window */
1655 #if TARGET_API_MAC_CARBON
1656 InvalWindowRect((WindowRef)(td->w), (const Rect *)(&portRect));
1658 InvalRect(&portRect);
1661 /* Display the window if needed */
1662 if (td->mapped) ShowWindow(td->w);
1664 /* Hack -- set "mapped" flag */
1665 t->mapped_flag = td->mapped;
1671 /* if (err == noErr)
1682 static void Term_nuke_mac(term *t)
1695 static errr Term_user_mac(int n)
1709 static errr Term_xtra_mac_react(void)
1711 term_data *td = (term_data*)(Term->data);
1717 #ifdef ANGBAND_LITE_MAC
1721 #else /* ANGBAND_LITE_MAC */
1724 if (use_sound != arg_sound)
1727 use_sound = arg_sound;
1731 /* Handle transparency */
1732 if (use_newstyle_graphics != arg_newstyle_graphics)
1736 if (globe_init() != 0)
1738 plog("Cannot initialize graphics!");
1739 arg_graphics = FALSE;
1740 arg_newstyle_graphics = FALSE;
1744 use_newstyle_graphics = arg_newstyle_graphics;
1746 /* Apply and Verify */
1747 term_data_check_size(td);
1749 /* Resize the window */
1750 term_data_resize(td);
1756 /* Handle graphics */
1757 if (use_graphics != arg_graphics)
1759 /* Initialize graphics */
1761 if (!use_graphics && !frameP && (globe_init() != 0))
1764 plog("¥°¥é¥Õ¥£¥Ã¥¯¤Î½é´ü²½¤Ï½ÐÍè¤Þ¤»¤ó¤Ç¤·¤¿.");
1766 plog("Cannot initialize graphics!");
1768 arg_graphics = FALSE;
1772 use_graphics = arg_graphics;
1774 /* Apply and Verify */
1775 term_data_check_size(td);
1777 /* Resize the window */
1778 term_data_resize(td);
1784 #endif /* ANGBAND_LITE_MAC */
1792 * Do a "special thing"
1794 static errr Term_xtra_mac(int n, int v)
1796 term_data *td = (term_data*)(Term->data);
1804 case TERM_XTRA_NOISE:
1813 #ifdef ANGBAND_LITE_MAC
1817 #else /* ANGBAND_LITE_MAC */
1820 case TERM_XTRA_SOUND:
1830 /* Open the resource file */
1831 oldResFile = CurResFile();
1832 newResFile = OpenResFile(sound);
1834 /* Close the resource file */
1835 CloseResFile(newResFile);
1836 UseResFile(oldResFile);
1839 /* Get the proper sound name */
1840 sprintf((char*)sound + 1, "%.16s.wav", angband_sound_name[v]);
1841 sound[0] = strlen((char*)sound + 1);
1843 /* Obtain resource XXX XXX XXX */
1844 handle = Get1NamedResource('snd ', sound);
1845 if( handle == NULL || ext_sound )
1846 handle = GetNamedResource('snd ', sound);
1849 if (handle && soundmode[soundchoice[v]] == true)
1852 LoadResource(handle);
1855 /* Play sound (wait for completion) */
1856 SndPlay(nil, (SndListHandle)handle, true);
1858 /* Unlock and release */
1860 ReleaseResource(handle);
1866 #endif /* ANGBAND_LITE_MAC */
1868 /* Process random events */
1869 case TERM_XTRA_BORED:
1871 /* Process an event */
1872 (void)CheckEvents(FALSE);
1878 /* Process pending events */
1879 case TERM_XTRA_EVENT:
1881 /* Process an event */
1882 (void)CheckEvents(v);
1888 /* Flush all pending events (if any) */
1889 case TERM_XTRA_FLUSH:
1891 /* Hack -- flush all events */
1892 while (CheckEvents(TRUE)) /* loop */;
1898 /* Hack -- Change the "soft level" */
1899 case TERM_XTRA_LEVEL:
1901 /* Activate if requested */
1902 if (v) activate(td->w);
1908 /* Clear the screen */
1909 case TERM_XTRA_CLEAR:
1913 #if TARGET_API_MAC_CARBON
1914 GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &portRect );
1915 global_to_local( &portRect );
1917 portRect = td->w->portRect;
1920 /* No clipping XXX XXX XXX */
1921 ClipRect(&portRect);
1923 /* Erase the window */
1924 EraseRect(&portRect);
1927 term_data_color(td, TERM_WHITE);
1929 /* Frame the window in white */
1931 LineTo(0, td->size_hgt-1);
1932 LineTo(td->size_wid-1, td->size_hgt-1);
1933 LineTo(td->size_wid-1, 0);
1935 /* Clip to the new size */
1936 r.left = portRect.left + td->size_ow1;
1937 r.top = portRect.top + td->size_oh1;
1938 r.right = portRect.right - td->size_ow2;
1939 r.bottom = portRect.bottom - td->size_oh2;
1946 /* React to changes */
1947 case TERM_XTRA_REACT:
1949 /* React to changes */
1950 return (Term_xtra_mac_react());
1953 /* Delay (milliseconds) */
1954 case TERM_XTRA_DELAY:
1959 #if TARGET_API_MAC_CARBON
1963 /* Convert millisecs to ticks */
1964 ticks = (v * 60L) / 1000;
1967 * Hack? - Put the programme into sleep.
1968 * No events match ~everyEvent, so nothing
1969 * should be lost in Angband's event queue.
1970 * Even if ticks are 0, it's worth calling for
1971 * the above mentioned reasons.
1973 WaitNextEvent(~everyEvent, &tmp, ticks, nil);
1975 long m = TickCount() + (v * 60L) / 1000;
1978 while (TickCount() < m) /* loop */;
1994 * Low level graphics (Assumes valid input).
1995 * Draw a "cursor" at (x,y), using a "yellow box".
1996 * We are allowed to use "Term_grab()" to determine
1997 * the current screen contents (for inverting, etc).
1999 static errr Term_curs_mac(int x, int y)
2003 term_data *td = (term_data*)(Term->data);
2006 term_data_color(td, TERM_YELLOW);
2008 /* Frame the grid */
2009 r.left = x * td->tile_wid + td->size_ow1;
2010 r.right = r.left + td->tile_wid;
2011 r.top = y * td->tile_hgt + td->size_oh1;
2012 r.bottom = r.top + td->tile_hgt;
2022 * Low level graphics (Assumes valid input).
2023 * Draw a "big cursor" at (x,y), using a "yellow box".
2024 * We are allowed to use "Term_grab()" to determine
2025 * the current screen contents (for inverting, etc).
2027 static errr Term_bigcurs_mac(int x, int y)
2031 term_data *td = (term_data*)(Term->data);
2034 term_data_color(td, TERM_YELLOW);
2036 /* Frame the grid */
2037 r.left = x * td->tile_wid + td->size_ow1;
2038 r.right = r.left + 2 * td->tile_wid;
2039 r.top = y * td->tile_hgt + td->size_oh1;
2040 r.bottom = r.top + td->tile_hgt;
2050 * Low level graphics (Assumes valid input)
2052 * Erase "n" characters starting at (x,y)
2054 static errr Term_wipe_mac(int x, int y, int n)
2058 term_data *td = (term_data*)(Term->data);
2060 /* Erase the block of characters */
2061 r.left = x * td->tile_wid + td->size_ow1;
2062 r.right = r.left + n * td->tile_wid;
2063 r.top = y * td->tile_hgt + td->size_oh1;
2064 r.bottom = r.top + td->tile_hgt;
2073 * Low level graphics. Assumes valid input.
2075 * Draw several ("n") chars, with an attr, at a given location.
2077 static errr Term_text_mac(int x, int y, int n, byte a, const char *cp)
2081 term_data *td = (term_data*)(Term->data);
2084 term_data_color(td, (a & 0x0F));
2086 /* Starting pixel */
2087 xp = x * td->tile_wid + td->tile_o_x + td->size_ow1;
2088 yp = y * td->tile_hgt + td->tile_o_y + td->size_oh1;
2090 /* Move to the correct location */
2093 /* Draw the character */
2094 if (n == 1) DrawChar(*cp);
2096 /* Draw the string */
2097 else DrawText(cp, 0, n);
2105 * Low level graphics (Assumes valid input)
2107 * Erase "n" characters starting at (x,y)
2109 static errr Term_pict_mac(int x, int y, int n, const byte *ap, const char *cp,
2110 const byte *tap, const char *tcp)
2114 term_data *td = (term_data*)(Term->data);
2115 GDHandle saveGDevice;
2116 GWorldPtr saveGWorld;
2118 PixMapHandle PortPix;
2121 GetGWorld(&saveGWorld, &saveGDevice);
2123 r2.left = x * td->tile_wid + td->size_ow1;
2124 r2.right = r2.left + td->tile_wid;
2125 r2.top = y * td->tile_hgt + td->size_oh1;
2126 r2.bottom = r2.top + td->tile_hgt;
2130 /* Instantiate font */
2131 TextFont(td->font_id);
2132 TextSize(td->font_size);
2133 TextFace(td->font_face);
2135 /* Restore colors */
2136 BackColor(blackColor);
2137 ForeColor(whiteColor);
2141 /* Destination rectangle */
2142 /* r2.left = x * td->tile_wid + td->size_ow1;
2143 r2.top = y * td->tile_hgt + td->size_oh1;
2144 r2.bottom = r2.top + td->tile_hgt;*/
2148 /* Scan the input */
2149 for (i = 0; i < n; i++)
2156 /* Second byte of bigtile */
2157 if (use_bigtile && a == 255)
2160 r2.left += td->tile_wid;
2165 /* Prepare right of rectangle now */
2166 r2.right = r2.left + td->tile_wid;
2168 #ifdef ANGBAND_LITE_MAC
2172 #else /* ANGBAND_LITE_MAC */
2174 /* Graphics -- if Available and Needed */
2175 if (use_graphics && ((byte)a & 0x80) && ((byte)c & 0x80))
2177 #if TARGET_API_MAC_CARBON
2178 PixMapHandle srcBitMap = GetGWorldPixMap(frameP->framePort);
2179 PixMapHandle destBitMap;
2181 BitMapPtr srcBitMap = (BitMapPtr)(frameP->framePix);
2182 BitMapPtr destBitMap;
2189 bool terrain_flag = FALSE;
2193 if ((a != ta || c != tc) &&
2194 ((byte)ta & 0x80) && ((byte)tc & 0x80))
2197 row = ((byte)ta & 0x7F);
2198 col = ((byte)tc & 0x7F);
2200 /* Terrain Source rectangle */
2201 terrain_r.left = col * grafWidth;
2202 terrain_r.top = row * grafHeight;
2203 terrain_r.right = terrain_r.left + grafWidth;
2204 terrain_r.bottom = terrain_r.top + grafHeight;
2206 terrain_flag = TRUE;
2210 row = ((byte)a & 0x7F);
2211 col = ((byte)c & 0x7F);
2213 /* Source rectangle */
2214 r1.left = col * grafWidth;
2215 r1.top = row * grafHeight;
2216 r1.right = r1.left + grafWidth;
2217 r1.bottom = r1.top + grafHeight;
2219 /* Hardwire CopyBits */
2220 BackColor(whiteColor);
2221 ForeColor(blackColor);
2223 /* Draw the picture */
2224 #if TARGET_API_MAC_CARBON
2225 destBitMap = GetPortPixMap(GetWindowPort( td->w ));
2227 destBitMap = (BitMapPtr)&(td->w->portBits);
2229 if (use_bigtile) r2.right += td->tile_wid;
2234 * Source mode const = srcCopy:
2236 * determine how close the color of the source
2237 * pixel is to black, and assign this relative
2238 * amount of foreground color to the
2239 * destination pixel; determine how close the
2240 * color of the source pixel is to white, and
2241 * assign this relative amount of background
2242 * color to the destination pixel
2244 #if TARGET_API_MAC_CARBON
2245 CopyBits( (BitMap *) *srcBitMap, (BitMap *) *destBitMap, &terrain_r, &r2, srcCopy, NULL);
2247 CopyBits( srcBitMap, destBitMap, &terrain_r, &r2, srcCopy, NULL );
2250 * Draw transparent tile
2251 * BackColor is ignored and the destination is
2254 BackColor(blackColor);
2255 #if TARGET_API_MAC_CARBON
2256 CopyBits( (BitMap *) *srcBitMap, (BitMap *) *destBitMap, &r1, &r2, transparent, NULL);
2258 CopyBits( srcBitMap, destBitMap, &r1, &r2, transparent, NULL );
2263 #if TARGET_API_MAC_CARBON
2264 CopyBits( (BitMap *) *srcBitMap, (BitMap *) *destBitMap, &r1, &r2, srcCopy, NULL);
2266 CopyBits( srcBitMap, destBitMap, &r1, &r2, srcCopy, NULL );
2270 /* Restore colors */
2271 BackColor(blackColor);
2272 ForeColor(whiteColor);
2281 #endif /* ANGBAND_LITE_MAC */
2289 term_data_color(td, (a & 0x0F));
2291 /* Starting pixel */
2292 xp = r2.left + td->tile_o_x;
2293 yp = r2.top + td->tile_o_y;
2295 /* Move to the correct location */
2301 /* Double width rectangle */
2302 r2.right += td->tile_wid;
2307 /* Draw the character */
2312 r2.left += td->tile_wid;
2320 /* Draw the character */
2326 r2.left += td->tile_wid;
2335 * Create and initialize window number "i"
2337 static void term_data_link(int i)
2341 term_data *td = &data[i];
2346 /* Require mapped */
2347 if (!td->mapped) return;
2352 /* Initialize the term */
2353 term_init(td->t, td->cols, td->rows, td->keys);
2355 /* Use a "software" cursor */
2356 td->t->soft_cursor = TRUE;
2358 /* Erase with "white space" */
2359 td->t->attr_blank = TERM_WHITE;
2360 td->t->char_blank = ' ';
2362 /* Prepare the init/nuke hooks */
2363 td->t->init_hook = Term_init_mac;
2364 td->t->nuke_hook = Term_nuke_mac;
2366 /* Prepare the function hooks */
2367 td->t->user_hook = Term_user_mac;
2368 td->t->xtra_hook = Term_xtra_mac;
2369 td->t->wipe_hook = Term_wipe_mac;
2370 td->t->curs_hook = Term_curs_mac;
2371 td->t->bigcurs_hook = Term_bigcurs_mac;
2372 td->t->text_hook = Term_text_mac;
2373 td->t->pict_hook = Term_pict_mac;
2375 /* Link the local structure */
2376 td->t->data = (vptr)(td);
2379 Term_activate(td->t);
2381 /* Global pointer */
2382 angband_term[i] = td->t;
2392 * Set the "current working directory" (also known as the "default"
2393 * volume/directory) to the location of the current application.
2395 * Code by: Maarten Hazewinkel (mmhazewi@cs.ruu.nl)
2397 * This function does not appear to work correctly with System 6.
2399 static void SetupAppDir(void)
2403 char errString[100];
2405 /* Get the location of the Angband executable */
2406 fcbBlock.ioCompletion = NULL;
2407 fcbBlock.ioNamePtr = NULL;
2408 fcbBlock.ioVRefNum = 0;
2409 fcbBlock.ioRefNum = CurResFile();
2410 fcbBlock.ioFCBIndx = 0;
2411 err = PBGetFCBInfo(&fcbBlock, FALSE);
2415 sprintf(errString, "PBGetFCBInfo ¥¨¥é¡¼ #%d.\r ½ªÎ»¤·¤Þ¤¹.", err);
2417 sprintf(errString, "Fatal PBGetFCBInfo Error #%d.\r Exiting.", err);
2419 mac_warning(errString);
2423 /* Extract the Vol and Dir */
2424 app_vol = fcbBlock.ioFCBVRefNum;
2425 app_dir = fcbBlock.ioFCBParID;
2427 /* Set the current working directory to that location */
2428 err = HSetVol(NULL, app_vol, app_dir);
2432 sprintf(errString, "HSetVol ¥¨¥é¡¼ #%d.\r ½ªÎ»¤·¤Þ¤¹.", err);
2434 sprintf(errString, "Fatal HSetVol Error #%d.\r Exiting.", err);
2436 mac_warning(errString);
2443 #ifdef TARGET_API_MAC_CARBON
2445 * Using Core Foundation's Preferences services -- pelpel
2447 * Requires OS 8.6 or greater with CarbonLib 1.1 or greater. Or OS X,
2450 * Without this, we can support older versions of OS 8 as well
2451 * (with CarbonLib 1.0.4).
2453 * Frequent allocation/deallocation of small chunks of data is
2454 * far from my liking, but since this is only called at the
2455 * beginning and the end of a session, I hope this hardly matters.
2460 * Store "value" as the value for preferences item name
2463 static void save_pref_short(const char *key, short value)
2466 CFNumberRef cf_value;
2468 /* allocate and initialise the key */
2469 cf_key = CFStringCreateWithCString(NULL, key, kTextEncodingUS_ASCII);
2471 /* allocate and initialise the value */
2472 cf_value = CFNumberCreate(NULL, kCFNumberShortType, &value);
2474 if ((cf_key != NULL) && (cf_value != NULL))
2476 /* Store the key-value pair in the applications preferences */
2477 CFPreferencesSetAppValue(
2480 kCFPreferencesCurrentApplication);
2484 * Free CF data - the reverse order is a vain attempt to
2485 * minimise memory fragmentation.
2487 if (cf_value) CFRelease(cf_value);
2488 if (cf_key) CFRelease(cf_key);
2493 * Load preference value for key, returns TRUE if it succeeds with
2494 * vptr updated appropriately, FALSE otherwise.
2496 static bool query_load_pref_short(const char *key, short *vptr)
2499 CFNumberRef cf_value;
2501 /* allocate and initialise the key */
2502 cf_key = CFStringCreateWithCString(NULL, key, kTextEncodingUS_ASCII);
2505 if (cf_key == NULL) return (FALSE);
2507 /* Retrieve value for the key */
2508 cf_value = CFPreferencesCopyAppValue(
2510 kCFPreferencesCurrentApplication);
2512 /* Value not found */
2513 if (cf_value == NULL)
2519 /* Convert the value to short */
2526 CFRelease(cf_value);
2535 * Update short data pointed by vptr only if preferences
2536 * value for key is located.
2538 static void load_pref_short(const char *key, short *vptr)
2542 if (query_load_pref_short(key, &tmp)) *vptr = tmp;
2548 * Save preferences to preferences file for current host+current user+
2549 * current application.
2551 static void cf_save_prefs()
2556 save_pref_short("version.major", FAKE_VERSION);
2557 save_pref_short("version.minor", FAKE_VER_MAJOR);
2558 save_pref_short("version.patch", FAKE_VER_MINOR);
2559 save_pref_short("version.extra", FAKE_VER_PATCH);
2562 save_pref_short("arg.arg_sound", arg_sound);
2563 save_pref_short("arg.arg_graphics", arg_graphics);
2564 save_pref_short("arg.arg_newstyle_graphics", arg_newstyle_graphics);
2565 save_pref_short("arg.arg_bigtile", arg_bigtile);
2568 for( i = 0 ; i < 7 ; i++ )
2569 save_pref_short(format("sound%d.on", i), soundmode[i]);
2572 for (i = 0; i < MAX_TERM_DATA; i++)
2574 term_data *td = &data[i];
2576 save_pref_short(format("term%d.mapped", i), td->mapped);
2578 save_pref_short(format("term%d.font_id", i), td->font_id);
2579 save_pref_short(format("term%d.font_size", i), td->font_size);
2580 save_pref_short(format("term%d.font_face", i), td->font_face);
2582 save_pref_short(format("term%d.tile_wid", i), td->tile_wid);
2583 save_pref_short(format("term%d.tile_hgt", i), td->tile_hgt);
2585 save_pref_short(format("term%d.cols", i), td->cols);
2586 save_pref_short(format("term%d.rows", i), td->rows);
2587 save_pref_short(format("term%d.left", i), td->r.left);
2588 save_pref_short(format("term%d.top", i), td->r.top);
2592 * Make sure preferences are persistent
2594 CFPreferencesAppSynchronize(
2595 kCFPreferencesCurrentApplication);
2600 * Load preferences from preferences file for current host+current user+
2601 * current application.
2603 static void cf_load_prefs()
2606 short pref_major, pref_minor, pref_patch, pref_extra;
2611 /* Assume nothing is wrong, yet */
2614 /* Load version information */
2615 ok &= query_load_pref_short("version.major", &pref_major);
2616 ok &= query_load_pref_short("version.minor", &pref_minor);
2617 ok &= query_load_pref_short("version.patch", &pref_patch);
2618 ok &= query_load_pref_short("version.extra", &pref_extra);
2620 /* Any of the above failed */
2623 /* This may be the first run */
2625 mac_warning("½é´üÀßÄê¥Õ¥¡¥¤¥ë¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó¡£");
2627 mac_warning("Preferences are not found.");
2630 /* Ignore the rest */
2637 if ((pref_major != PREF_VER_MAJOR) ||
2638 (pref_minor != PREF_VER_MINOR) ||
2639 (pref_patch != PREF_VER_PATCH) ||
2640 (pref_extra != PREF_VER_EXTRA))
2644 format("Ignoring %d.%d.%d.%d preferences.",
2645 pref_major, pref_minor, pref_patch, pref_extra));
2658 if (query_load_pref_short("arg.arg_sound", &pref_tmp))
2659 arg_sound = pref_tmp;
2662 if (query_load_pref_short("arg.arg_graphics", &pref_tmp))
2663 arg_graphics = pref_tmp;
2665 /*newstyle graphics*/
2666 if (query_load_pref_short("arg.arg_newstyle_graphics", &pref_tmp))
2668 use_newstyle_graphics = pref_tmp;
2671 if (use_newstyle_graphics == true)
2673 ANGBAND_GRAF = "new";
2674 arg_newstyle_graphics = true;
2675 grafWidth = grafHeight = 16;
2680 ANGBAND_GRAF = "old";
2681 arg_newstyle_graphics = false;
2682 grafWidth = grafHeight = 8;
2686 /* double-width tiles */
2687 if (query_load_pref_short("arg.arg_bigtile", &pref_tmp))
2689 use_bigtile = pref_tmp;
2695 for( i = 0 ; i < 7 ; i++ )
2697 query_load_pref_short(format("sound%d.on", i), &soundmode[i]);
2701 m = GetMenuHandle(134);
2703 /* Item "arg_sound" */
2704 CheckMenuItem(m, 1, arg_sound);
2706 /* Item "arg_graphics" */
2707 CheckMenuItem(m, 2, arg_graphics);
2709 /* Item "arg_newstyle_graphics"*/
2710 CheckMenuItem(m, 8, arg_newstyle_graphics);
2712 /* Item "arg_bigtile"*/
2713 CheckMenuItem(m, 9, arg_bigtile);
2716 for (i = 0; i < MAX_TERM_DATA; i++)
2718 term_data *td = &data[i];
2720 load_pref_short(format("term%d.mapped", i), &td->mapped);
2722 load_pref_short(format("term%d.font_id", i), &td->font_id);
2723 load_pref_short(format("term%d.font_size", i), &td->font_size);
2724 load_pref_short(format("term%d.font_face", i), &td->font_face);
2726 load_pref_short(format("term%d.tile_wid", i), &td->tile_wid);
2727 load_pref_short(format("term%d.tile_hgt", i), &td->tile_hgt);
2729 load_pref_short(format("term%d.cols", i), &td->cols);
2730 load_pref_short(format("term%d.rows", i), &td->rows);
2731 load_pref_short(format("term%d.left", i), &td->r.left);
2732 load_pref_short(format("term%d.top", i), &td->r.top);
2738 * Global "preference" file pointer
2743 * Read a "short" from the file
2745 static int getshort(void)
2749 if (0 == my_fgets(fff, buf, sizeof(buf))) x = atoi(buf);
2754 * Dump a "short" to the file
2756 static void putshort(int x)
2758 fprintf(fff, "%d\n", x);
2764 * Write the "preference" data to the current "file"
2766 static void save_prefs(void)
2773 /*** The current version ***/
2775 putshort(FAKE_VERSION);
2776 putshort(FAKE_VER_MAJOR);
2777 putshort(FAKE_VER_MINOR);
2778 putshort(FAKE_VER_PATCH);
2780 putshort(arg_sound);
2781 putshort(arg_graphics);
2782 putshort(arg_newstyle_graphics);
2783 putshort(arg_bigtile);
2786 for( i = 0 ; i < 7 ; i++ )
2787 putshort(soundmode[i]);
2790 for (i = 0; i < MAX_TERM_DATA; i++)
2795 putshort(td->mapped);
2797 putshort(td->font_id);
2798 putshort(td->font_size);
2799 putshort(td->font_face);
2801 putshort(td->tile_wid);
2802 putshort(td->tile_hgt);
2807 putshort(td->r.left);
2808 putshort(td->r.top);
2814 * Load the preferences from the current "file"
2816 * XXX XXX XXX Being able to undefine various windows is
2817 * slightly bizarre, and may cause problems.
2819 static void load_prefs(void)
2823 int old_version, old_major, old_minor, old_patch;
2828 /*** Version information ***/
2830 /* Preferences version */
2831 old_version = getshort();
2832 old_major = getshort();
2833 old_minor = getshort();
2834 old_patch = getshort();
2836 /* Hack -- Verify or ignore */
2837 if ((old_version != FAKE_VERSION) ||
2838 (old_major != FAKE_VER_MAJOR) ||
2839 (old_minor != FAKE_VER_MINOR) ||
2840 (old_patch != FAKE_VER_PATCH))
2844 mac_warning("¸Å¤¤½é´üÀßÄê¥Õ¥¡¥¤¥ë¤ò̵»ë¤·¤Þ¤¹.");
2846 mac_warning("Ignoring old preferences.");
2852 arg_sound = getshort();
2853 arg_graphics = getshort();
2854 arg_newstyle_graphics = getshort();
2855 use_newstyle_graphics = arg_newstyle_graphics;
2857 if (use_newstyle_graphics == true)
2859 ANGBAND_GRAF = "new";
2860 arg_newstyle_graphics = true;
2861 grafWidth = grafHeight = 16;
2866 ANGBAND_GRAF = "old";
2867 arg_newstyle_graphics = false;
2868 grafWidth = grafHeight = 8;
2872 arg_bigtile = getshort();
2873 use_bigtile = arg_bigtile;
2876 for( i = 0 ; i < 7 ; i++ )
2877 soundmode[i] = getshort();
2880 m = GetMenuHandle(134);
2882 #if TARGET_API_MAC_CARBON
2883 /* Item "arg_sound" */
2884 CheckMenuItem(m, 1, arg_sound);
2886 /* Item "arg_graphics" */
2887 CheckMenuItem(m, 2, arg_graphics);
2889 /* Item "arg_newstyle_graphics"*/
2890 CheckMenuItem(m, 8, arg_newstyle_graphics);
2892 /* Item "arg_sound" */
2893 CheckItem(m, 1, arg_sound);
2895 /* Item "arg_graphics" */
2896 CheckItem(m, 2, arg_graphics);
2898 /* Item "arg_newstyle_graphics"*/
2899 CheckItem(m, 8, arg_newstyle_graphics);
2903 for (i = 0; i < MAX_TERM_DATA; i++)
2908 td->mapped = getshort();
2910 td->font_id = getshort();
2911 td->font_size = getshort();
2912 td->font_face = getshort();
2914 td->tile_wid = getshort();
2915 td->tile_hgt = getshort();
2917 td->cols = getshort();
2918 td->rows = getshort();
2920 td->r.left = getshort();
2921 td->r.top = getshort();
2924 if (feof(fff)) break;
2927 #endif /* TARGET_API_MAC_CARBON */
2932 * Hack -- default data for a window
2934 static void term_data_hack(term_data *td)
2938 #if TARGET_API_MAC_CARBON
2940 /* Default to Osaka font (Japanese) */
2941 fid = FMGetFontFamilyFromName( "\pOsaka¡ÝÅùÉý" );
2943 /* Default to Monaco font */
2944 fid = FMGetFontFamilyFromName("\pmonaco");
2948 /* Default to ÅùÉýÌÀÄ« font (Japanese) */
2949 GetFNum( "\pÅùÉýÌÀÄ«", &fid);
2950 SetFScaleDisable( true );
2952 /* Default to Monaco font */
2953 GetFNum("\pmonaco", &fid);
2958 WIPE(td, term_data);
2963 /* Default borders */
2974 /* Default font size */
2977 /* Default font face */
2984 /* Default position */
2994 * Read the preference file, Create the windows.
2996 * We attempt to use "FindFolder()" to track down the preference file,
2997 * but if this fails, for any reason, we will try the "SysEnvirons()"
2998 * method, which may work better with System 6.
3000 static void init_windows(void)
3013 /*** Default values ***/
3015 /* Initialize (backwards) */
3016 for (i = MAX_TERM_DATA - 1; i >= 0; i--)
3029 s = angband_term_name[i];
3034 /* Maximal length */
3037 /* Copy the title */
3038 strncpy((char*)(td->title) + 1, s, n);
3040 /* Save the length */
3043 /* Tile the windows */
3044 td->r.left += (b * 30);
3045 td->r.top += (b * 30);
3052 /*** Load preferences ***/
3054 #ifdef TARGET_API_MAC_CARBON
3057 /* Assume failure */
3060 /* Assume failure */
3073 /* Find the folder */
3074 err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
3080 /* Extract a path name */
3081 PathNameFromDirID(dirID, vref, (StringPtr)foo);
3083 /* Convert the string */
3084 ptocstr((StringPtr)foo);
3086 /* Append the preference file name */
3087 strcat(foo, PREF_FILE_NAME);
3089 /* Open the preference file */
3090 fff = fopen(foo, "r");
3097 #endif /* USE_SFL_CODE */
3103 HGetVol(0, &savev, &saved);
3105 /* Go to the "system" folder */
3106 SysEnvirons(curSysEnvVers, &env);
3107 SetVol(0, env.sysVRefNum);
3110 fff = fopen(PREF_FILE_NAME, "r");
3113 HSetVol(0, savev, saved);
3116 /* Load preferences */
3119 /* Load a real preference file */
3122 /* Close the file */
3128 /*** Instantiate ***/
3139 /* Link (backwards, for stacking order) */
3140 for (i = MAX_TERM_DATA - 1; i >= 0; i--)
3149 Term_activate(td->t);
3152 static void init_sound( void )
3156 SignedByte permission = fsRdPerm;
3162 /* Descend into "lib" folder */
3163 pb.dirInfo.ioCompletion = NULL;
3164 pb.dirInfo.ioNamePtr = "\plib";
3165 pb.dirInfo.ioVRefNum = app_vol;
3166 pb.dirInfo.ioDrDirID = app_dir;
3167 pb.dirInfo.ioFDirIndex = 0;
3169 /* Check for errors */
3170 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3173 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3175 /* Descend into "lib/save" folder */
3176 pb.dirInfo.ioCompletion = NULL;
3177 pb.dirInfo.ioNamePtr = "\pxtra";
3178 pb.dirInfo.ioVRefNum = app_vol;
3179 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3180 pb.dirInfo.ioFDirIndex = 0;
3182 /* Check for errors */
3183 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3186 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3188 /* Descend into "lib/save" folder */
3189 pb.dirInfo.ioCompletion = NULL;
3190 pb.dirInfo.ioNamePtr = "\psound";
3191 pb.dirInfo.ioVRefNum = app_vol;
3192 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3193 pb.dirInfo.ioFDirIndex = 0;
3195 /* Check for errors */
3196 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3199 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3201 ret = HOpenResFile( app_vol , pb.dirInfo.ioDrDirID , "\psound.rsrc" , permission );
3205 for( i = 0 ; i < 7 ; i++ )
3206 soundmode[i] = false;
3208 for( i = 1 ; i < SOUND_MAX ; i++ ){
3209 /* Get the proper sound name */
3210 sprintf((char*)sound + 1, "%.16s.wav", angband_sound_name[i]);
3211 sound[0] = strlen((char*)sound + 1);
3213 /* Obtain resource XXX XXX XXX */
3214 handle = Get1NamedResource('snd ', sound);
3215 if( handle == NULL || ext_sound )
3216 handle = GetNamedResource('snd ', sound);
3219 soundmode[soundchoice[i]] = true;
3228 static void init_graf( void )
3232 SignedByte permission = fsRdPerm;
3238 /* Descend into "lib" folder */
3239 pb.dirInfo.ioCompletion = NULL;
3240 pb.dirInfo.ioNamePtr = "\plib";
3241 pb.dirInfo.ioVRefNum = app_vol;
3242 pb.dirInfo.ioDrDirID = app_dir;
3243 pb.dirInfo.ioFDirIndex = 0;
3245 /* Check for errors */
3246 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3249 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3251 /* Descend into "lib/xtra" folder */
3252 pb.dirInfo.ioCompletion = NULL;
3253 pb.dirInfo.ioNamePtr = "\pxtra";
3254 pb.dirInfo.ioVRefNum = app_vol;
3255 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3256 pb.dirInfo.ioFDirIndex = 0;
3258 /* Check for errors */
3259 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3262 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3264 /* Descend into "lib/xtra/graf" folder */
3265 pb.dirInfo.ioCompletion = NULL;
3266 pb.dirInfo.ioNamePtr = "\pgraf";
3267 pb.dirInfo.ioVRefNum = app_vol;
3268 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrDirID;
3269 pb.dirInfo.ioFDirIndex = 0;
3271 /* Check for errors */
3272 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3275 if ((err == noErr) && (pb.dirInfo.ioFlAttrib & 0x10))
3277 ret = HOpenResFile( app_vol , pb.dirInfo.ioDrDirID , "\pgraf.rsrc" , permission );
3282 /* Obtain resource XXX XXX XXX */
3283 handle = Get1NamedResource('PICT', graf);
3284 if ( handle == NULL || ext_graf )
3285 handle = GetNamedResource('PICT', "\pgraf.rsrc");
3296 static void init_chuukei( void )
3302 path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "chuukei.txt");
3304 fp = fopen(path, "r");
3309 if (fgets(tmp, 1024, fp)){
3311 int n = strlen(tmp);
3317 chuukei_server = TRUE;
3318 if(connect_chuukei_server(&tmp[2])<0){
3319 msg_print("connect fail");
3322 msg_print("connect");
3329 chuukei_client = TRUE;
3330 connect_chuukei_server(&tmp[2]);
3346 short InevrtCheck( DialogPtr targetDlg, short check )
3353 GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
3354 result = (GetControlValue( (ControlHandle)checkH ) + 1 ) % 2;
3355 SetControlValue( (ControlHandle)checkH , result );
3363 short SetCheck( DialogPtr targetDlg, short check, long result )
3370 GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
3371 SetControlValue( (ControlHandle)checkH , result );
3379 short GetCheck( DialogPtr targetDlg, short check )
3386 GetDialogItem( targetDlg, check, &itemType, &checkH, &box );
3387 result = GetControlValue( (ControlHandle)checkH );
3391 void SoundConfigDLog(void)
3398 dialog=GetNewDialog(131, 0, (WindowPtr)-1);
3399 SetDialogDefaultItem( dialog, ok );
3400 SetDialogCancelItem( dialog, cancel );
3401 for( i = 1 ; i < 7 ; i++ )
3402 SetCheck( dialog, i+2 , soundmode[i] );
3404 /* ShowWindow(dialog); */
3405 for( item_hit = 100 ; cancel < item_hit ; ){
3406 ModalDialog(0, &item_hit);
3410 for( i = 1 ; i < 7 ; i++ )
3411 soundmode[i] = GetCheck( dialog, i+2 );
3416 InevrtCheck( dialog, item_hit );
3419 DisposeDialog(dialog);
3427 #if TARGET_API_MAC_CARBON
3428 static void save_pref_file(void)
3433 static void save_pref_file(void)
3442 /* Assume failure */
3445 /* Assume failure */
3462 /* Find the folder */
3463 err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
3469 /* Extract a path name */
3470 PathNameFromDirID(dirID, vref, (StringPtr)foo);
3472 /* Convert the string */
3473 ptocstr((StringPtr)foo);
3475 /* Append the preference file name */
3476 strcat(foo, PREF_FILE_NAME);
3478 /* Open the preference file */
3479 /* my_fopen set file type and file creator for MPW */
3480 fff = my_fopen(foo, "w");
3487 #endif /* USE_SFL_CODE */
3493 HGetVol(0, &savev, &saved);
3495 /* Go to "system" folder */
3496 SysEnvirons(curSysEnvVers, &env);
3497 SetVol(0, env.sysVRefNum);
3499 /* Open the preference file */
3500 /* my_fopen set file type and file creator for MPW */
3501 fff = fopen(PREF_FILE_NAME, "w");
3504 HSetVol(0, savev, saved);
3507 /* Save preferences */
3510 /* Write the preferences */
3522 * A simple "Yes/No" filter to parse "key press" events in dialog windows
3524 static pascal Boolean ynfilter(DialogPtr dialog, EventRecord *event, short *ip)
3526 /* Parse key press events */
3527 if (event->what == keyDown)
3532 /* Extract the pressed key */
3533 c = (event->message & charCodeMask);
3535 /* Accept "no" and <return> and <enter> */
3536 if ((c=='n') || (c=='N') || (c==13) || (c==3)) i = 1;
3539 else if ((c=='y') || (c=='Y')) i = 2;
3541 /* Handle "yes" or "no" */
3545 ControlHandle control;
3548 /* Get the button */
3549 GetDialogItem(dialog, i, &type, (Handle*)&control, &r);
3551 /* Blink button for 1/10 second */
3552 HiliteControl(control, 1);
3553 Term_xtra_mac(TERM_XTRA_DELAY, 100);
3554 HiliteControl(control, 0);
3568 * Handle menu: "File" + "New"
3570 static void do_menu_file_new(void)
3575 /* Game is in progress */
3576 game_in_progress = 1;
3590 * Handle menu: "File" + "Open"
3592 #if TARGET_API_MAC_CARBON
3593 static void do_menu_file_open(bool all)
3607 refnum_to_name(path, app_dir, app_vol, (char*)("\plib:save:"));
3609 FSpLocationFromFullPath( strlen(path), path, &fsp );
3612 ChooseFile( (StringPtr)savefile, fsp );
3615 if (err != noErr) return;
3617 /* Extract textual file name for save file */
3618 /* GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
3619 refnum_to_name(savefile, drefnum, vrefnum, (char*)reply.fName);
3624 /* Game is in progress */
3625 game_in_progress = 1;
3637 static void do_menu_file_open(bool all)
3651 /* vrefnum = GetSFCurVol(); */
3652 vrefnum = -*((short*)0x214);
3654 /* drefnum = GetSFCurDir(); */
3655 drefnum = *((long*)0x398);
3657 /* Descend into "lib" folder */
3658 pb.ioCompletion = NULL;
3659 pb.ioNamePtr = "\plib";
3660 pb.ioVRefNum = vrefnum;
3661 pb.ioDrDirID = drefnum;
3664 /* Check for errors */
3665 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3668 if ((err == noErr) && (pb.ioFlAttrib & 0x10))
3670 /* Descend into "lib/save" folder */
3671 pb.ioCompletion = NULL;
3672 pb.ioNamePtr = "\psave";
3673 pb.ioVRefNum = vrefnum;
3674 pb.ioDrDirID = pb.ioDrDirID;
3677 /* Check for errors */
3678 err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
3681 if ((err == noErr) && (pb.ioFlAttrib & 0x10))
3683 /* SetSFCurDir(pb.ioDrDirID); */
3684 *((long*)0x398) = pb.ioDrDirID;
3688 /* Window location */
3689 topleft.h = (qd.screenBits.bounds.left+qd.screenBits.bounds.right)/2-344/2;
3690 topleft.v = (2*qd.screenBits.bounds.top+qd.screenBits.bounds.bottom)/3-188/2;
3692 /* Allow "all" files */
3696 SFGetFile(topleft, "\p", NULL, -1, types, NULL, &reply);
3699 /* Allow "save" files */
3706 SFGetFile(topleft, "\p", NULL, 1, types, NULL, &reply);
3710 if (!reply.good) return;
3712 /* Extract textual file name for save file */
3713 GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
3714 refnum_to_name(savefile, drefnum, vrefnum, (char*)reply.fName);
3719 /* Game is in progress */
3720 game_in_progress = 1;
3735 * Handle the "open_when_ready" flag
3737 static void handle_open_when_ready(void)
3739 /* Check the flag XXX XXX XXX make a function for this */
3740 if (open_when_ready && initialized && !game_in_progress)
3743 open_when_ready = FALSE;
3745 /* Game is in progress */
3746 game_in_progress = 1;
3765 * Initialize the menus
3767 * Verify menus 128, 129, 130
3768 * Create menus 131, 132, 133, 134
3770 * The standard menus are:
3772 * Apple (128) = { About, -, ... }
3773 * File (129) = { New,Open,Import,Close,Save,-,Exit,Quit }
3774 * Edit (130) = { Cut, Copy, Paste, Clear } (?)
3775 * Font (131) = { Bold, Extend, -, Monaco, ..., -, ... }
3776 * Size (132) = { ... }
3777 * Window (133) = { Angband, Mirror, Recall, Choice,
3778 * Term-4, Term-5, Term-6, Term-7 }
3779 * Special (134) = { arg_sound, arg_graphics, -,
3780 * arg_fiddle, arg_wizard }
3782 static void init_menubar(void)
3794 /* Get the "apple" menu */
3797 /* Insert the menu */
3800 /* Add the DA's to the "apple" menu */
3801 #if TARGET_API_MAC_CARBON
3803 AppendResMenu (m, 'DRVR');
3806 /* Get the "File" menu */
3807 #if TARGET_API_MAC_CARBON
3809 err = Gestalt( gestaltSystemVersion, &response );
3810 if ( (err == noErr) && (response >= 0x00000A00) )
3812 DeleteMenuItem( m, 7 );
3818 /* Insert the menu */
3822 /* Get the "Edit" menu */
3825 /* Insert the menu */
3829 /* Make the "Font" menu */
3831 m = NewMenu(131, "\p¥Õ¥©¥ó¥È");
3833 m = NewMenu(131, "\pFont");
3836 /* Insert the menu */
3840 AppendMenu(m, "\pBold");
3843 AppendMenu(m, "\pWide");
3845 /* Add a separator */
3846 AppendMenu(m, "\p-");
3849 r.left = r.right = r.top = r.bottom = 0;
3851 /* Make the fake window */
3852 tmpw = NewWindow(0, &r, "\p", false, documentProc, 0, 0, 0);
3854 /* Activate the "fake" window */
3855 #if TARGET_API_MAC_CARBON
3856 SetPortWindowPort(tmpw);
3867 /* Add the fonts to the menu */
3868 AppendResMenu(m, 'FONT');
3871 #if TARGET_API_MAC_CARBON
3872 n = CountMenuItems(m);
3878 for (i = n; i >= 4; i--)
3883 /* Acquire the font name */
3884 GetMenuItemText(m, i, tmpName);
3886 /* Acquire the font index */
3887 #if TARGET_API_MAC_CARBON
3888 fontNum = FMGetFontFamilyFromName( tmpName );
3890 GetFNum(tmpName, &fontNum);
3893 /* Apply the font index */
3896 /* Remove non-mono-spaced fonts */
3897 if ((CharWidth('i') != CharWidth('W')) || (CharWidth('W') == 0))
3899 /* Delete the menu item XXX XXX XXX */
3900 DeleteMenuItem (m, i);
3904 /* Destroy the old window */
3905 DisposeWindow(tmpw);
3907 /* Add a separator */
3908 AppendMenu(m, "\p-");
3910 /* Add the fonts to the menu */
3911 AppendResMenu (m, 'FONT');
3914 /* Make the "Size" menu */
3916 m = NewMenu(132, "\p¥µ¥¤¥º");
3918 m = NewMenu(132, "\pSize");
3921 /* Insert the menu */
3924 /* Add some sizes (stagger choices) */
3925 for (i = 8; i <= 32; i += ((i / 16) + 1))
3930 sprintf((char*)buf + 1, "%d", i);
3931 buf[0] = strlen((char*)buf + 1);
3938 /* Make the "Windows" menu */
3940 m = NewMenu(133, "\p¥¦¥¤¥ó¥É¥¦");
3942 m = NewMenu(133, "\pWindows");
3945 /* Insert the menu */
3948 /* Default choices */
3949 for (i = 0; i < MAX_TERM_DATA; i++)
3953 /* Describe the item */
3954 sprintf((char*)buf + 1, "%.15s", angband_term_name[i]);
3955 buf[0] = strlen((char*)buf + 1);
3960 /* Command-Key shortcuts */
3961 if (i < 8) SetItemCmd(m, i + 1, '0' + i);
3965 /* Make the "Special" menu */
3967 m = NewMenu(134, "\pÆÃÊÌ");
3969 m = NewMenu(134, "\pSpecial");
3972 /* Insert the menu */
3975 /* Append the choices */
3977 AppendMenu(m, "\p¥µ¥¦¥ó¥É»ÈÍÑ");
3978 AppendMenu(m, "\p¥°¥é¥Õ¥£¥Ã¥¯»ÈÍÑ");
3979 AppendMenu(m, "\p-");
3980 AppendMenu(m, "\parg_fiddle");
3981 AppendMenu(m, "\parg_wizard");
3982 AppendMenu(m, "\p-");
3983 AppendMenu(m, "\p¥µ¥¦¥ó¥ÉÀßÄê...");
3984 AppendMenu(m, "\p16X16¥°¥é¥Õ¥£¥Ã¥¯");
3985 AppendMenu(m, "\p£²ÇÜÉý¥¿¥¤¥ëɽ¼¨");
3987 AppendMenu(m, "\parg_sound");
3988 AppendMenu(m, "\parg_graphics");
3989 AppendMenu(m, "\p-");
3990 AppendMenu(m, "\parg_fiddle");
3991 AppendMenu(m, "\parg_wizard");
3992 AppendMenu(m, "\p-");
3993 AppendMenu(m, "\pSound config");
3994 AppendMenu(m, "\pAdam Bolt tile");
3995 AppendMenu(m, "\pBigtile Mode");
3998 /* Make the "TileWidth" menu */
4000 m = NewMenu(135, "\p¥¿¥¤¥ëÉý");
4002 m = NewMenu(135, "\pTileWidth");
4005 /* Insert the menu */
4008 /* Add some sizes */
4009 for (i = 4; i <= 32; i++)
4014 sprintf((char*)buf + 1, "%d", i);
4015 buf[0] = strlen((char*)buf + 1);
4022 /* Make the "TileHeight" menu */
4024 m = NewMenu(136, "\p¥¿¥¤¥ë¹â");
4026 m = NewMenu(136, "\pTileHeight");
4029 /* Insert the menu */
4032 /* Add some sizes */
4033 for (i = 4; i <= 32; i++)
4038 sprintf((char*)buf + 1, "%d", i);
4039 buf[0] = strlen((char*)buf + 1);
4046 /* Update the menu bar */
4054 static void setup_menus(void)
4064 term_data *td = NULL;
4067 /* Relevant "term_data" */
4068 for (i = 0; i < MAX_TERM_DATA; i++)
4071 if (!data[i].t) continue;
4073 /* Notice the matching window */
4074 if (data[i].w == FrontWindow()) td = &data[i];
4079 m = GetMenuHandle(129);
4082 #if TARGET_API_MAC_CARBON
4083 n = CountMenuItems(m);
4089 for (i = 1; i <= n; i++)
4092 #if TARGET_API_MAC_CARBON
4093 DisableMenuItem(m, i);
4094 CheckMenuItem(m, i, FALSE);
4097 CheckItem(m, i, FALSE);
4101 /* Enable "new"/"open..."/"import..." */
4102 if (initialized && !game_in_progress)
4104 #if TARGET_API_MAC_CARBON
4105 EnableMenuItem(m, 1);
4106 EnableMenuItem(m, 2);
4107 EnableMenuItem(m, 3);
4115 /* Enable "close" */
4118 #if TARGET_API_MAC_CARBON
4119 EnableMenuItem(m, 4);
4126 if (initialized && character_generated)
4128 #if TARGET_API_MAC_CARBON
4129 EnableMenuItem(m, 5);
4138 #if TARGET_API_MAC_CARBON
4139 EnableMenuItem(m, 7);
4147 m = GetMenuHandle(130);
4150 #if TARGET_API_MAC_CARBON
4151 n = CountMenuItems(m);
4157 for (i = 1; i <= n; i++)
4160 #if TARGET_API_MAC_CARBON
4161 DisableMenuItem(m, i);
4162 CheckMenuItem(m, i, FALSE);
4165 CheckItem(m, i, FALSE);
4169 /* Enable "edit" options if "needed" */
4172 #if TARGET_API_MAC_CARBON
4173 EnableMenuItem(m, 1);
4174 EnableMenuItem(m, 3);
4175 EnableMenuItem(m, 4);
4176 EnableMenuItem(m, 5);
4177 EnableMenuItem(m, 6);
4189 m = GetMenuHandle(131);
4192 #if TARGET_API_MAC_CARBON
4193 n = CountMenuItems(m);
4199 for (i = 1; i <= n; i++)
4202 #if TARGET_API_MAC_CARBON
4203 DisableMenuItem(m, i);
4204 CheckMenuItem(m, i, FALSE);
4207 CheckItem(m, i, FALSE);
4211 /* Hack -- look cute XXX XXX */
4212 /* SetItemStyle(m, 1, bold); */
4214 /* Hack -- look cute XXX XXX */
4215 /* SetItemStyle(m, 2, extend); */
4220 #if TARGET_API_MAC_CARBON
4222 EnableMenuItem(m, 1);
4224 /* Enable "extend" */
4225 EnableMenuItem(m, 2);
4227 /* Check the appropriate "bold-ness" */
4228 if (td->font_face & bold) CheckMenuItem(m, 1, TRUE);
4230 /* Check the appropriate "wide-ness" */
4231 if (td->font_face & extend) CheckMenuItem(m, 2, TRUE);
4234 for (i = 4; i <= n; i++)
4237 EnableMenuItem(m, i);
4240 GetMenuItemText(m, i, s);
4243 /* Check active font */
4244 if (td->font_id == value) CheckMenuItem(m, i, TRUE);
4250 /* Enable "extend" */
4253 /* Check the appropriate "bold-ness" */
4254 if (td->font_face & bold) CheckItem(m, 1, TRUE);
4256 /* Check the appropriate "wide-ness" */
4257 if (td->font_face & extend) CheckItem(m, 2, TRUE);
4260 for (i = 4; i <= n; i++)
4266 GetMenuItemText(m, i, s);
4269 /* Check active font */
4270 if (td->font_id == value) CheckItem(m, i, TRUE);
4277 m = GetMenuHandle(132);
4280 #if TARGET_API_MAC_CARBON
4281 n = CountMenuItems(m);
4287 for (i = 1; i <= n; i++)
4290 #if TARGET_API_MAC_CARBON
4291 DisableMenuItem(m, i);
4292 CheckMenuItem(m, i, FALSE);
4295 CheckItem(m, i, FALSE);
4303 for (i = 1; i <= n; i++)
4305 #if TARGET_API_MAC_CARBON
4307 GetMenuItemText(m, i, s);
4309 value = atoi((char*)(s+1));
4311 /* Enable the "real" sizes */
4312 if (RealFont(td->font_id, value)) EnableMenuItem(m, i);
4314 /* Check the current size */
4315 if (td->font_size == value) CheckMenuItem(m, i, TRUE);
4318 GetMenuItemText(m, i, s);
4320 value = atoi((char*)(s+1));
4322 /* Enable the "real" sizes */
4323 if (RealFont(td->font_id, value)) EnableItem(m, i);
4325 /* Check the current size */
4326 if (td->font_size == value) CheckItem(m, i, TRUE);
4333 m = GetMenuHandle(133);
4336 #if TARGET_API_MAC_CARBON
4337 n = CountMenuItems(m);
4342 /* Check active windows */
4343 for (i = 1; i <= n; i++)
4345 /* Check if needed */
4346 #if TARGET_API_MAC_CARBON
4347 CheckMenuItem(m, i, data[i-1].mapped);
4349 CheckItem(m, i, data[i-1].mapped);
4355 m = GetMenuHandle(134);
4358 #if TARGET_API_MAC_CARBON
4359 n = CountMenuItems(m);
4365 for (i = 1; i <= n; i++)
4368 #if TARGET_API_MAC_CARBON
4369 DisableMenuItem(m, i);
4370 CheckMenuItem(m, i, FALSE);
4373 CheckItem(m, i, FALSE);
4377 #if TARGET_API_MAC_CARBON
4378 /* Item "arg_sound" */
4379 EnableMenuItem(m, 1);
4380 CheckMenuItem(m, 1, arg_sound);
4382 /* Item "arg_graphics" */
4383 EnableMenuItem(m, 2);
4384 CheckMenuItem(m, 2, arg_graphics);
4386 /* Item "arg_fiddle" */
4387 EnableMenuItem(m, 4);
4388 CheckMenuItem(m, 4, arg_fiddle);
4390 /* Item "arg_wizard" */
4391 EnableMenuItem(m, 5);
4392 CheckMenuItem(m, 5, arg_wizard);
4394 /* Item "SoundSetting" */
4395 EnableMenuItem(m, 7);
4397 /* Item NewStyle Graphics */
4398 EnableMenuItem(m, 8);
4399 CheckMenuItem(m, 8, use_newstyle_graphics);
4401 /* Item Bigtile Mode */
4402 EnableMenuItem(m, 9);
4403 CheckMenuItem(m, 9, arg_bigtile);
4405 /* Item "arg_sound" */
4407 CheckItem(m, 1, arg_sound);
4409 /* Item "arg_graphics" */
4411 CheckItem(m, 2, arg_graphics);
4413 /* Item "arg_fiddle" */
4415 CheckItem(m, 4, arg_fiddle);
4417 /* Item "arg_wizard" */
4419 CheckItem(m, 5, arg_wizard);
4421 /* Item "SoundSetting" */
4424 /* Item NewStyle Graphics */
4426 CheckItem(m, 8, use_newstyle_graphics);
4428 /* Item Bigtile Mode */
4430 CheckItem(m, 9, arg_bigtile);
4433 /* TileWidth menu */
4434 m = GetMenuHandle(135);
4437 #if TARGET_API_MAC_CARBON
4438 n = CountMenuItems(m);
4444 for (i = 1; i <= n; i++)
4447 #if TARGET_API_MAC_CARBON
4448 DisableMenuItem(m, i);
4449 CheckMenuItem(m, i, FALSE);
4452 CheckItem(m, i, FALSE);
4460 for (i = 1; i <= n; i++)
4463 /* GetMenuItemText(m,i,s); */
4464 GetMenuItemText(m, i, s);
4466 value = atoi((char*)(s+1));
4468 #if TARGET_API_MAC_CARBON
4470 EnableMenuItem(m, i);
4472 /* Check the current size */
4473 if (td->tile_wid == value) CheckMenuItem(m, i, TRUE);
4478 /* Check the current size */
4479 if (td->tile_wid == value) CheckItem(m, i, TRUE);
4485 /* TileHeight menu */
4486 m = GetMenuHandle(136);
4489 #if TARGET_API_MAC_CARBON
4490 n = CountMenuItems(m);
4496 for (i = 1; i <= n; i++)
4499 #if TARGET_API_MAC_CARBON
4500 DisableMenuItem(m, i);
4501 CheckMenuItem(m, i, FALSE);
4504 CheckItem(m, i, FALSE);
4512 for (i = 1; i <= n; i++)
4515 GetMenuItemText(m, i, s);
4517 value = atoi((char*)(s+1));
4519 #if TARGET_API_MAC_CARBON
4521 EnableMenuItem(m, i);
4523 /* Check the current size */
4524 if (td->tile_hgt == value) CheckMenuItem(m, i, TRUE);
4529 /* Check the current size */
4530 if (td->tile_hgt == value) CheckItem(m, i, TRUE);
4538 * Process a menu selection (see above)
4540 * Hack -- assume that invalid menu selections are disabled above,
4541 * which I have been informed may not be reliable. XXX XXX XXX
4543 static void menu(long mc)
4547 int menuid, selection;
4549 static unsigned char s[1000];
4553 term_data *td = NULL;
4558 /* Analyze the menu command */
4559 menuid = HiWord(mc);
4560 selection = LoWord(mc);
4563 /* Find the window */
4564 for (i = 0; i < MAX_TERM_DATA; i++)
4566 /* Skip dead windows */
4567 if (!data[i].t) continue;
4569 /* Notice matches */
4570 if (data[i].w == FrontWindow()) td = &data[i];
4574 /* Branch on the menu */
4580 /* About Angband... */
4581 #if TARGET_API_MAC_CARBON
4587 /* Get the about dialogue */
4588 dialog=GetNewDialog(128, 0, (WindowPtr)-1);
4590 /* Move it to the middle of the screen */
4592 GetDialogWindow(dialog),
4594 kWindowCenterOnMainScreen);
4596 /* Show the dialog */
4597 TransitionWindow(GetDialogWindow(dialog),
4598 kWindowZoomTransitionEffect,
4599 kWindowShowTransitionAction,
4602 /* Wait for user to click on it */
4603 ModalDialog(0, &item_hit);
4605 /* Free the dialogue */
4606 DisposeDialog(dialog);
4616 dialog=GetNewDialog(128, 0, (WindowPtr)-1);
4619 center_rect(&r, &qd.screenBits.bounds);
4620 MoveWindow(dialog, r.left, r.top, 1);
4622 ModalDialog(0, &item_hit);
4623 DisposeDialog(dialog);
4627 /* Desk accessory */
4628 /* GetMenuItemText(GetMHandle(128),selection,s); */
4629 GetMenuItemText(GetMenuHandle(128), selection, s);
4650 do_menu_file_open(FALSE);
4657 do_menu_file_open(TRUE);
4671 td->t->mapped_flag = FALSE;
4673 /* Hide the window */
4684 plog("º£¤Ï¥»¡¼¥Ö¤¹¤ë¤³¤È¤Ï½ÐÍè¤Þ¤»¤ó¡£");
4686 plog("You may not do that right now.");
4691 /* Hack -- Forget messages */
4694 /* Hack -- Save the game */
4695 do_cmd_save_game(FALSE);
4700 /* Quit (with save) */
4703 /* Save the game (if necessary) */
4704 if (game_in_progress && character_generated)
4708 plog("º£¤Ï¥»¡¼¥Ö¤¹¤ë¤³¤È¤Ï½ÐÍè¤Þ¤»¤ó¡£");
4710 plog("You may not do that right now.");
4714 /* Hack -- Forget messages */
4719 do_cmd_save_game(FALSE);
4721 Term_key_push(SPECIAL_KEY_QUIT);
4743 /* Require a window */
4752 /* Toggle the "bold" setting */
4755 /* Toggle the setting */
4756 if (td->font_face & bold)
4758 td->font_face &= ~bold;
4762 td->font_face |= bold;
4765 /* Tile Width Hight Init */
4766 td->tile_wid = td->tile_hgt = 0;
4768 /* Apply and Verify */
4769 term_data_check_font(td);
4770 term_data_check_size(td);
4772 /* Resize and Redraw */
4773 term_data_resize(td);
4774 term_data_redraw(td);
4779 /* Toggle the "wide" setting */
4782 /* Toggle the setting */
4783 if (td->font_face & extend)
4785 td->font_face &= ~extend;
4789 td->font_face |= extend;
4792 /* Tile Width Hight Init */
4793 td->tile_wid = td->tile_hgt = 0;
4795 /* Apply and Verify */
4796 term_data_check_font(td);
4797 term_data_check_size(td);
4799 /* Resize and Redraw */
4800 term_data_resize(td);
4801 term_data_redraw(td);
4806 /* Get a new font name */
4807 GetMenuItemText(GetMenuHandle(131), selection, s);
4810 /* Save the new font id */
4813 /* Current size is bad for new font */
4814 if (!RealFont(td->font_id, td->font_size))
4816 /* Find similar size */
4817 for (i = 1; i <= 32; i++)
4819 /* Adjust smaller */
4820 if (td->font_size - i >= 8)
4822 if (RealFont(td->font_id, td->font_size - i))
4830 if (td->font_size + i <= 128)
4832 if (RealFont(td->font_id, td->font_size + i))
4841 /* Tile Width Hight Init */
4842 td->tile_wid = td->tile_hgt = 0;
4844 /* Apply and Verify */
4845 term_data_check_font(td);
4846 term_data_check_size(td);
4848 /* Resize and Redraw */
4849 term_data_resize(td);
4850 term_data_redraw(td);
4852 /* Restore the window */
4869 GetMenuItemText(GetMenuHandle(132), selection, s);
4871 td->font_size = atoi((char*)(s+1));
4873 /* Tile Width Hight Init */
4874 td->tile_wid = td->tile_hgt = 0;
4876 /* Apply and Verify */
4877 term_data_check_font(td);
4878 term_data_check_size(td);
4880 /* Resize and Redraw */
4881 term_data_resize(td);
4882 term_data_redraw(td);
4896 /* Check legality of choice */
4897 if ((i < 0) || (i >= MAX_TERM_DATA)) break;
4899 /* Obtain the window */
4909 td->t->mapped_flag = TRUE;
4911 /* Show the window */
4914 /* Bring to the front */
4915 SelectWindow(td->w);
4927 /* Toggle arg_sound */
4928 arg_sound = !arg_sound;
4930 /* React to changes */
4931 Term_xtra(TERM_XTRA_REACT, 0);
4938 /* Toggle arg_graphics */
4939 arg_graphics = !arg_graphics;
4940 if( arg_graphics == true ){
4941 ANGBAND_GRAF = "old";
4942 arg_newstyle_graphics = false;
4943 grafWidth = grafHeight = 8;
4947 /* Hack -- Force redraw */
4948 Term_key_push(KTRL('R'));
4955 arg_fiddle = !arg_fiddle;
4961 arg_wizard = !arg_wizard;
4972 if (streq(ANGBAND_GRAF, "old"))
4974 ANGBAND_GRAF = "new";
4975 arg_newstyle_graphics = true;
4976 grafWidth = grafHeight = 16;
4981 ANGBAND_GRAF = "old";
4982 arg_newstyle_graphics = false;
4983 grafWidth = grafHeight = 8;
4987 /* Hack -- Force redraw */
4988 Term_key_push(KTRL('R'));
4992 case 9: /* bigtile mode */
4994 term_data *td = &data[0];
4998 plog("º£¤ÏÊѹ¹½ÐÍè¤Þ¤»¤ó¡£");
5000 plog("You may not do that right now.");
5005 /* Toggle "arg_bigtile" */
5006 arg_bigtile = !arg_bigtile;
5009 Term_activate(td->t);
5011 /* Resize the term */
5012 Term_resize(td->cols, td->rows);
5022 /* TileWidth menu */
5033 GetMenuItemText(GetMenuHandle(135), selection, s);
5035 td->tile_wid = atoi((char*)(s+1));
5037 /* Apply and Verify */
5038 term_data_check_size(td);
5040 /* Resize and Redraw */
5041 term_data_resize(td);
5042 term_data_redraw(td);
5050 /* TileHeight menu */
5061 GetMenuItemText(GetMenuHandle(136), selection, s);
5063 td->tile_hgt = atoi((char*)(s+1));
5065 /* Apply and Verify */
5066 term_data_check_size(td);
5068 /* Resize and Redraw */
5069 term_data_resize(td);
5070 term_data_redraw(td);
5080 /* Clean the menu */
5089 * Check for extra required parameters -- From "Maarten Hazewinkel"
5091 static OSErr CheckRequiredAEParams(const AppleEvent *theAppleEvent)
5094 DescType returnedType;
5097 aeError = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard,
5098 &returnedType, NULL, 0, &actualSize);
5100 if (aeError == errAEDescNotFound) return (noErr);
5102 if (aeError == noErr) return (errAEParamMissed);
5109 * Apple Event Handler -- Open Application
5111 static pascal OSErr AEH_Start(const AppleEvent *theAppleEvent,
5112 AppleEvent *reply, long handlerRefCon)
5114 #pragma unused(reply, handlerRefCon)
5116 return (CheckRequiredAEParams(theAppleEvent));
5121 * Apple Event Handler -- Quit Application
5123 static pascal OSErr AEH_Quit(const AppleEvent *theAppleEvent,
5124 AppleEvent *reply, long handlerRefCon)
5126 #pragma unused(reply, handlerRefCon)
5127 #if TARGET_API_MAC_CARBON
5129 /* Save the game (if necessary) */
5130 if (game_in_progress && character_generated)
5134 plog("º£¤Ï¥»¡¼¥Ö¤¹¤ë¤³¤È¤Ï½ÐÍè¤Þ¤»¤ó¡£");
5136 plog("You may not do that right now.");
5140 /* Hack -- Forget messages */
5145 do_cmd_save_game(FALSE);
5147 Term_key_push(SPECIAL_KEY_QUIT);
5155 quit_when_ready = TRUE;
5157 /* Check arguments */
5158 return (CheckRequiredAEParams(theAppleEvent));
5164 * Apple Event Handler -- Print Documents
5166 static pascal OSErr AEH_Print(const AppleEvent *theAppleEvent,
5167 AppleEvent *reply, long handlerRefCon)
5169 #pragma unused(theAppleEvent, reply, handlerRefCon)
5171 return (errAEEventNotHandled);
5176 * Apple Event Handler by Steve Linberg (slinberg@crocker.com).
5178 * The old method of opening savefiles from the finder does not work
5179 * on the Power Macintosh, because CountAppFiles and GetAppFiles,
5180 * used to return information about the selected document files when
5181 * an application is launched, are part of the Segment Loader, which
5182 * is not present in the RISC OS due to the new memory architecture.
5184 * The "correct" way to do this is with AppleEvents. The following
5185 * code is modeled on the "Getting Files Selected from the Finder"
5186 * snippet from Think Reference 2.0. (The prior sentence could read
5187 * "shamelessly swiped & hacked")
5189 static pascal OSErr AEH_Open(const AppleEvent *theAppleEvent,
5190 AppleEvent* reply, long handlerRefCon)
5192 #pragma unused(reply, handlerRefCon)
5199 DescType returnedType;
5203 /* Put the direct parameter (a descriptor list) into a docList */
5204 err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &docList);
5205 if (err) return err;
5208 * We ignore the validity check, because we trust the FInder, and we only
5209 * allow one savefile to be opened, so we ignore the depth of the list.
5212 err = AEGetNthPtr(&docList, 1L, typeFSS, &keywd,
5213 &returnedType, (Ptr) &myFSS, sizeof(myFSS), &actualSize);
5214 if (err) return err;
5216 /* Only needed to check savefile type below */
5217 err = FSpGetFInfo(&myFSS, &myFileInfo);
5220 sprintf(foo, "Arg! FSpGetFInfo failed with code %d", err);
5225 /* Ignore non 'SAVE' files */
5226 if (myFileInfo.fdType != 'SAVE') return noErr;
5228 /* XXX XXX XXX Extract a file name */
5229 PathNameFromDirID(myFSS.parID, myFSS.vRefNum, (StringPtr)savefile);
5230 pstrcat((StringPtr)savefile, (StringPtr)&myFSS.name);
5232 /* Convert the string */
5233 ptocstr((StringPtr)savefile);
5235 /* Delay actual open */
5236 open_when_ready = TRUE;
5239 err = AEDisposeDesc(&docList);
5251 * Macintosh modifiers (event.modifier & ccc):
5252 * cmdKey, optionKey, shiftKey, alphaLock, controlKey
5255 * Macintosh Keycodes (0-63 normal, 64-95 keypad, 96-127 extra):
5300 * Optimize non-blocking calls to "CheckEvents()"
5301 * Idea from "Maarten Hazewinkel <mmhazewi@cs.ruu.nl>"
5303 #define EVENT_TICKS 6
5307 * Check for Events, return TRUE if we process any
5309 * Hack -- Handle AppleEvents if appropriate (ignore result code).
5311 static bool CheckEvents(bool wait)
5327 term_data *td = NULL;
5331 static huge lastTicks = 0L;
5334 /* Access the clock */
5335 curTicks = TickCount();
5337 /* Hack -- Allow efficient checking for non-pending events */
5338 if (!wait && (curTicks < lastTicks + EVENT_TICKS)) return (FALSE);
5340 /* Timestamp last check */
5341 lastTicks = curTicks;
5343 #if TARGET_API_MAC_CARBON
5344 WaitNextEvent( everyEvent, &event, 1L, nil );
5346 /* Let the "system" run */
5349 /* Get an event (or null) */
5350 GetNextEvent(everyEvent, &event);
5353 /* Hack -- Nothing is ready yet */
5354 if (event.what == nullEvent) return (FALSE);
5356 /* Analyze the event */
5364 w = (WindowPtr)event.message;
5375 /* Extract the window */
5376 w = (WindowPtr)event.message;
5378 /* Find the window */
5379 for (i = 0; i < MAX_TERM_DATA; i++)
5381 /* Skip dead windows */
5382 if (!data[i].t) continue;
5384 /* Notice matches */
5385 if (data[i].w == w) td = &data[i];
5388 /* Hack XXX XXX XXX */
5392 /* Redraw the window */
5393 if (td) term_data_redraw(td);
5401 /* Extract some modifiers */
5402 mc = (event.modifiers & controlKey) ? TRUE : FALSE;
5403 ms = (event.modifiers & shiftKey) ? TRUE : FALSE;
5404 mo = (event.modifiers & optionKey) ? TRUE : FALSE;
5405 mx = (event.modifiers & cmdKey) ? TRUE : FALSE;
5407 /* Keypress: (only "valid" if ck < 96) */
5408 ch = (event.message & charCodeMask) & 255;
5410 /* Keycode: see table above */
5411 ck = ((event.message & keyCodeMask) >> 8) & 255;
5413 /* Command + "normal key" -> menu action */
5414 if (mx && (ck < 64))
5416 /* Hack -- Prepare the menus */
5419 /* Run the Menu-Handler */
5422 /* Turn off the menus */
5430 /* Hide the mouse pointer */
5433 /* Normal key -> simple keypress */
5436 /* Enqueue the keypress */
5440 /* Bizarre key -> encoded keypress */
5443 /* Hack -- introduce with control-underscore */
5446 /* Send some modifier keys */
5447 if (mc) Term_keypress('C');
5448 if (ms) Term_keypress('S');
5449 if (mo) Term_keypress('O');
5450 if (mx) Term_keypress('X');
5452 /* Hack -- Downshift and encode the keycode */
5453 Term_keypress('0' + (ck - 64) / 10);
5454 Term_keypress('0' + (ck - 64) % 10);
5456 /* Hack -- Terminate the sequence */
5457 /* MPW can generate 10 or 13 for keycode of '\r' */
5458 /* -noMapCR option swaps '\r' and '\n' */
5459 Term_keypress('\r');
5469 /* Analyze click location */
5470 code = FindWindow(event.where, &w);
5472 /* Find the window */
5473 for (i = 0; i < MAX_TERM_DATA; i++)
5475 /* Skip dead windows */
5476 if (!data[i].t) continue;
5478 /* Notice matches */
5479 if (data[i].w == w) td = &data[i];
5488 menu(MenuSelect(event.where));
5492 #if !TARGET_API_MAC_CARBON
5495 SystemClick(&event, w);
5507 #if TARGET_API_MAC_CARBON
5508 GetQDGlobalsScreenBits( &screen );
5510 screen = qd.screenBits;
5513 r.top += 20; /* GetMBarHeight() XXX XXX XXX */
5514 InsetRect(&r, 4, 4);
5515 DragWindow(w, event.where, &r);
5527 #if TARGET_API_MAC_CARBON
5528 GetWindowBounds( (WindowRef)td->w, kWindowContentRgn, &portRect );
5530 portRect = td->w->portRect;
5531 local_to_global( &portRect );
5533 p.h = portRect.left;
5535 #if !TARGET_API_MAC_CARBON
5544 /* Apply and Verify */
5545 term_data_check_size(td);
5555 /* Track the go-away box */
5556 if (TrackGoAway(w, event.where))
5562 td->t->mapped_flag = FALSE;
5564 /* Hide the window */
5578 #if TARGET_API_MAC_CARBON
5579 GetQDGlobalsScreenBits( &screen );
5581 screen = qd.screenBits;
5586 /* Fake rectangle */
5587 r.left = 20 * td->tile_wid + td->size_ow1;
5588 r.right = screen.bounds.right;
5589 r.top = 1 * td->tile_hgt + td->size_oh1;
5590 r.bottom = screen.bounds.bottom;
5592 /* Grow the rectangle */
5593 newsize = GrowWindow(w, event.where, &r);
5596 if (!newsize) break;
5598 /* Extract the new size in pixels */
5599 y = HiWord(newsize) - td->size_oh1 - td->size_oh2;
5600 x = LoWord(newsize) - td->size_ow1 - td->size_ow2;
5602 /* Extract a "close" approximation */
5603 td->rows = y / td->tile_hgt;
5604 td->cols = x / td->tile_wid;
5606 /* Apply and Verify */
5607 term_data_check_size(td);
5609 Term_activate(td->t);
5611 /* Hack -- Resize the term */
5612 Term_resize(td->cols, td->rows);
5614 /* Resize and Redraw */
5615 term_data_resize(td);
5616 term_data_redraw(td);
5635 /* Disk Event -- From "Maarten Hazewinkel" */
5639 #if TARGET_API_MAC_CARBON
5641 /* check for error when mounting the disk */
5642 if (HiWord(event.message) != noErr)
5648 DIBadMount(p, event.message);
5655 /* OS Event -- From "Maarten Hazewinkel" */
5658 switch ((event.message >> 24) & 0x000000FF)
5660 case suspendResumeMessage:
5662 /* Resuming: activate the front window */
5663 if (event.message & resumeFlag)
5665 #if TARGET_API_MAC_CARBON
5668 SetPortWindowPort( FrontWindow() );
5670 GetQDGlobalsArrow( &arrow );
5673 SetPort(FrontWindow());
5674 SetCursor(&qd.arrow);
5678 /* Suspend: deactivate the front window */
5692 /* From "Steve Linberg" and "Maarten Hazewinkel" */
5693 case kHighLevelEvent:
5695 #if TARGET_API_MAC_CARBON
5696 AEProcessAppleEvent(&event);
5698 /* Process apple events */
5699 if (AEProcessAppleEvent(&event) != noErr)
5702 plog("Apple Event Handler¤Î¥¨¥é¡¼¤Ç¤¹.");
5704 plog("Error in Apple Event Handler!");
5708 /* Handle "quit_when_ready" */
5709 if (quit_when_ready)
5712 quit_when_ready = FALSE;
5714 /* Do the menu key */
5717 /* Turn off the menus */
5721 /* Handle "open_when_ready" */
5722 handle_open_when_ready();
5733 /* Something happened */
5740 /*** Some Hooks for various routines ***/
5744 * Mega-Hack -- emergency lifeboat
5746 static vptr lifeboat = NULL;
5750 * Hook to "release" memory
5752 static vptr hook_rnfree(vptr v, huge size)
5755 #pragma unused (size)
5759 /* Alternative method */
5774 * Hook to "allocate" memory
5776 static vptr hook_ralloc(huge size)
5781 /* Make a new pointer */
5782 return (malloc(size));
5786 /* Make a new pointer */
5787 return (NewPtr(size));
5794 * Hook to handle "out of memory" errors
5796 static vptr hook_rpanic(huge size)
5799 #pragma unused (size)
5803 /* Free the lifeboat */
5806 /* Free the lifeboat */
5807 DisposePtr(lifeboat);
5809 /* Forget the lifeboat */
5812 /* Mega-Hack -- Warning */
5814 mac_warning("¥á¥â¥ê¡¼¤¬Â¤ê¤Þ¤»¤ó!\rº£¤¹¤°½ªÎ»¤·¤Æ²¼¤µ¤¤!");
5816 mac_warning("Running out of Memory!\rAbort this process now!");
5819 /* Mega-Hack -- Never leave this function */
5820 while (TRUE) CheckEvents(TRUE);
5823 /* Mega-Hack -- Crash */
5829 * Hook to tell the user something important
5831 static void hook_plog(cptr str)
5833 /* Warning message */
5838 * Hook to tell the user something, and then quit
5840 static void hook_quit(cptr str)
5842 /* Warning if needed */
5843 if (str) mac_warning(str);
5845 /* Write a preference file */
5853 * Hook to tell the user something, and then crash
5855 static void hook_core(cptr str)
5857 /* XXX Use the debugger */
5858 /* DebugStr(str); */
5861 if (str) mac_warning(str);
5863 /* Warn, then save player */
5865 mac_warning("Ã×̿Ū¤Ê¥¨¥é¡¼¤Ç¤¹.\r¶¯À©Åª¤Ë¥»¡¼¥Ö¤·¤Æ½ªÎ»¤·¤Þ¤¹.");
5867 mac_warning("Fatal error.\rI will now attempt to save and quit.");
5870 /* Attempt to save */
5872 if (!save_player()) mac_warning("·Ù¹ð -- ¥»¡¼¥Ö¤Ë¼ºÇÔ¤·¤Þ¤·¤¿!");
5874 if (!save_player()) mac_warning("Warning -- save failed!");
5883 /*** Main program ***/
5889 * XXX XXX XXX Hack -- This function attempts to "fix" the nasty
5890 * "Macintosh Save Bug" by using "absolute" path names, since on
5891 * System 7 machines anyway, the "current working directory" often
5892 * "changes" due to background processes, invalidating any "relative"
5893 * path names. Note that the Macintosh is limited to 255 character
5894 * path names, so be careful about deeply embedded directories...
5896 * XXX XXX XXX Hack -- This function attempts to "fix" the nasty
5897 * "missing lib folder bug" by allowing the user to help find the
5898 * "lib" folder by hand if the "application folder" code fails...
5900 static void init_stuff(void)
5919 #if TARGET_API_MAC_CARBON
5921 NavDialogOptions dialogOptions;
5922 FSSpec theFolderSpec;
5923 NavReplyRecord theReply;
5925 /* Fake rectangle */
5932 #if TARGET_API_MAC_CARBON
5933 screenRect = GetQDGlobalsScreenBits(&screen)->bounds;
5935 screenRect = qd.screenBits.bounds;
5937 center_rect(&r, &screenRect);
5939 /* Extract corner */
5944 /* Default to the "lib" folder with the application */
5945 refnum_to_name(path, app_dir, app_vol, (char*)("\plib:"));
5948 /* Check until done */
5951 /* Prepare the paths */
5952 init_file_paths(path);
5954 /* Build the filename */
5956 path_build(path, sizeof(path), ANGBAND_DIR_FILE, "news_j.txt");
5958 path_build(path, sizeof(path), ANGBAND_DIR_FILE, "news.txt");
5961 /* Attempt to open and close that file */
5962 if (0 == fd_close(fd_open(path, O_RDONLY))) break;
5966 plog_fmt("'%s' ¥Õ¥¡¥¤¥ë¤ò¥ª¡¼¥×¥ó½ÐÍè¤Þ¤»¤ó.", path);
5968 plog_fmt("Unable to open the '%s' file.", path);
5973 plog("Hengband¤Î'lib'¥Õ¥©¥ë¥À¤¬Â¸ºß¤·¤Ê¤¤¤«Àµ¤·¤¯Ìµ¤¤²ÄǽÀ¤¬¤¢¤ê¤Þ¤¹.");
5975 plog("The Angband 'lib' folder is probably missing or misplaced.");
5980 plog("Please 'open' any file in any sub-folder of the 'lib' folder.");
5982 plog("Please 'open' any file in any sub-folder of the 'lib' folder.");
5985 #if TARGET_API_MAC_CARBON
5986 /* Ask the user to choose the lib folder */
5987 err = NavGetDefaultDialogOptions(&dialogOptions);
5990 if (err != noErr) quit(NULL);
5992 /* Set default location option */
5993 dialogOptions.dialogOptionFlags |= kNavSelectDefaultLocation;
5995 /* Clear preview option */
5996 dialogOptions.dialogOptionFlags &= ~(kNavAllowPreviews);
5998 /* Forbit selection of multiple files */
5999 dialogOptions.dialogOptionFlags &= ~(kNavAllowMultipleFiles);
6001 /* Display location */
6002 dialogOptions.location = topleft;
6004 /* Load the message for the missing folder from the resource fork */
6005 GetIndString(dialogOptions.message, 128, 1);
6007 /* Wait for the user to choose a folder */
6008 err = NavChooseFolder(
6016 /* Assume the player doesn't want to go on */
6017 if ((err != noErr) || !theReply.validRecord) quit(NULL);
6019 /* Retrieve FSSpec from the reply */
6021 AEKeyword theKeyword;
6022 DescType actualType;
6025 /* Get a pointer to selected folder */
6027 &(theReply.selection),
6037 if (err != noErr) quit(NULL);
6040 /* Free navitagor reply */
6041 err = NavDisposeReply(&theReply);
6044 if (err != noErr) quit(NULL);
6046 /* Extract textual file name for given file */
6049 theFolderSpec.parID,
6050 theFolderSpec.vRefNum,
6051 (char *)theFolderSpec.name);
6053 /* Allow "text" files */
6056 /* Allow "save" files */
6059 /* Allow "data" files */
6063 SFGetFile(topleft, "\p", NULL, 3, types, NULL, &reply);
6066 if (!reply.good) quit(NULL);
6068 /* Extract textual file name for given file */
6069 GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
6070 refnum_to_name(path, drefnum, vrefnum, (char*)reply.fName);
6073 /* Hack -- Remove the "filename" */
6074 i = strlen(path) - 1;
6075 while ((i > 0) && (path[i] != ':')) i--;
6076 if (path[i] == ':') path[i+1] = '\0';
6078 /* Hack -- allow "lib" folders */
6079 if (suffix(path, "lib:")) continue;
6081 /* Hack -- Remove the "sub-folder" */
6083 while ((i > 1) && (path[i] != ':')) i--;
6084 if (path[i] == ':') path[i+1] = '\0';
6090 * Macintosh Main loop
6094 EventRecord tempEvent;
6095 int numberOfMasters = 10;
6097 #if !TARGET_API_MAC_CARBON
6098 /* Increase stack space by 64K */
6099 SetApplLimit(GetApplLimit() - 131072L);//65536L);
6101 /* Stretch out the heap to full size */
6105 /* Get more Masters */
6106 while (numberOfMasters--) MoreMasters();
6108 #if !TARGET_API_MAC_CARBON
6109 /* Set up the Macintosh */
6110 InitGraf(&qd.thePort);
6124 FlushEvents(everyEvent, 0);
6126 /* Flush events some more (?) */
6127 (void)EventAvail(everyEvent, &tempEvent);
6128 (void)EventAvail(everyEvent, &tempEvent);
6129 (void)EventAvail(everyEvent, &tempEvent);
6132 #ifdef ANGBAND_LITE_MAC
6136 #else /* ANGBAND_LITE_MAC */
6138 # if defined(powerc) || defined(__powerc)
6140 /* Assume System 7 */
6142 /* Assume Color Quickdraw */
6152 /* Check the Gestalt */
6153 err = Gestalt(gestaltSystemVersion, &versionNumber);
6155 /* Check the version */
6156 if ((err != noErr) || (versionNumber < 0x0700))
6159 quit("¤³¤Î¥×¥í¥°¥é¥à¤Ï´Á»úTalk7.x.x°Ê¹ß¤ÇÆ°ºî¤·¤Þ¤¹.");
6161 quit("You must have System 7 to use this program.");
6171 /* Check the environs */
6172 if (SysEnvirons(1, &env) != noErr)
6175 quit("SysEnvirons ¥³¡¼¥ë¤Ï¼ºÇÔ¤·¤Þ¤·¤¿¡ª");
6177 quit("The SysEnvirons call failed!");
6181 /* Check for System Seven Stuff */
6182 if (env.systemVersion < 0x0700)
6185 quit("¤³¤Î¥×¥í¥°¥é¥à¤Ï´Á»úTalk7.x.x°Ê¹ß¤ÇÆ°ºî¤·¤Þ¤¹.");
6187 quit("You must have System 7 to use this program.");
6191 /* Check for Color Quickdraw */
6192 if (!env.hasColorQD)
6195 quit("¤³¤Î¥×¥í¥°¥é¥à¤ÏColor Quickdraw¤¬Ìµ¤¤¤ÈÆ°ºî¤·¤Þ¤»¤ó.");
6197 quit("You must have Color Quickdraw to use this program.");
6204 #endif /* ANGBAND_LITE_MAC */
6207 * Remember Mac OS version, in case we have to cope with version-specific
6210 (void)Gestalt(gestaltSystemVersion, &mac_os_version);
6213 /* Obtain a "Universal Procedure Pointer" */
6214 AEH_Start_UPP = NewAEEventHandlerUPP(AEH_Start);
6215 /* Install the hook (ignore error codes) */
6216 AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, AEH_Start_UPP,
6219 /* Obtain a "Universal Procedure Pointer" */
6220 AEH_Quit_UPP = NewAEEventHandlerUPP(AEH_Quit);
6221 /* Install the hook (ignore error codes) */
6222 AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, AEH_Quit_UPP,
6225 /* Obtain a "Universal Procedure Pointer" */
6226 AEH_Print_UPP = NewAEEventHandlerUPP(AEH_Print);
6227 /* Install the hook (ignore error codes) */
6228 AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, AEH_Print_UPP,
6231 /* Obtain a "Universal Procedure Pointer" */
6232 AEH_Open_UPP = NewAEEventHandlerUPP(AEH_Open);
6233 /* Install the hook (ignore error codes) */
6234 AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, AEH_Open_UPP,
6238 /* Find the current application */
6242 /* Mark ourself as the file creator */
6245 /* Default to saving a "text" file */
6249 #if defined(__MWERKS__)
6251 /* Obtian a "Universal Procedure Pointer" */
6252 #if TARGET_API_MAC_CARBON
6253 ynfilterUPP = NewModalFilterUPP(ynfilter);
6255 ynfilterUPP = NewModalFilterProc(ynfilter);
6261 /* Hook in some "z-virt.c" hooks */
6262 rnfree_aux = hook_rnfree;
6263 ralloc_aux = hook_ralloc;
6264 rpanic_aux = hook_rpanic;
6266 /* Hooks in some "z-util.c" hooks */
6267 plog_aux = hook_plog;
6268 quit_aux = hook_quit;
6269 core_aux = hook_core;
6271 BackColor(blackColor);
6272 ForeColor(whiteColor);
6274 /* Show the "watch" cursor */
6275 SetCursor(*(GetCursor(watchCursor)));
6277 /* Prepare the menubar */
6280 /* Prepare the windows */
6287 /* Hack -- process all events */
6288 while (CheckEvents(TRUE)) /* loop */;
6290 /* Reset the cursor */
6291 #if TARGET_API_MAC_CARBON
6294 GetQDGlobalsArrow( &arrow );
6298 SetCursor( &qd.arrow );
6302 /* Mega-Hack -- Allocate a "lifeboat" */
6303 lifeboat = NewPtr(16384);
6305 /* Note the "system" */
6306 ANGBAND_SYS = "mac";
6311 /* Catch nasty signals */
6318 /* Hack -- process all events */
6319 while (CheckEvents(TRUE)) /* loop */;
6322 /* We are now initialized */
6326 /* Handle "open_when_ready" */
6327 handle_open_when_ready();
6333 /* Prompt the user */
6335 prt("'¥Õ¥¡¥¤¥ë'¥á¥Ë¥å¡¼¤è¤ê'¿·µ¬'¤Þ¤¿¤Ï'³«¤¯...'¤òÁªÂò¤·¤Æ¤¯¤À¤µ¤¤¡£", 23, 10);
6337 prt("[Choose 'New' or 'Open' from the 'File' menu]", 23, 15);
6340 /* Flush the prompt */
6344 /* Hack -- Process Events Forever */
6345 while (TRUE) CheckEvents(TRUE);