OSDN Git Service

upgrade to 3.6.1
[jnethack/source.git] / sys / mac / macmain.c
1 /* NetHack 3.6  macmain.c       $NHDT-Date: 1432512796 2015/05/25 00:13:16 $  $NHDT-Branch: master $:$NHDT-Revision: 1.21 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2009. */
4 /* NetHack may be freely redistributed.  See license for details. */
5
6 /* main.c - Mac NetHack */
7
8 #include "hack.h"
9 #include "dlb.h"
10 #include "macwin.h"
11 #include "mactty.h"
12
13 #if 1 /*!TARGET_API_MAC_CARBON*/
14 #include <OSUtils.h>
15 #include <files.h>
16 #include <Types.h>
17 #include <Dialogs.h>
18 #include <Packages.h>
19 #include <ToolUtils.h>
20 #include <Resources.h>
21 #include <Errors.h>
22 #endif
23
24 #ifndef O_RDONLY
25 #include <fcntl.h>
26 #endif
27
28 static void finder_file_request(void);
29 int main(void);
30
31 #if __SC__ || __MRC__
32 QDGlobals qd;
33 #endif
34
35 int
36 main(void)
37 {
38     register int fd = -1;
39     int argc = 1;
40     boolean resuming = FALSE; /* assume new game */
41
42     sys_early_init();
43     windowprocs = mac_procs;
44     InitMac();
45
46     hname = "Mac Hack";
47     hackpid = getpid();
48
49     setrandom();
50     initoptions();
51     init_nhwindows(&argc, (char **) &hname);
52
53     /*
54      * It seems you really want to play.
55      */
56     u.uhp = 1; /* prevent RIP on early quits */
57
58     finder_file_request();
59
60     dlb_init(); /* must be before newgame() */
61
62     /*
63      *  Initialize the vision system.  This must be before mklev() on a
64      *  new game or before a level restore on a saved game.
65      */
66     vision_init();
67
68     display_gamewindows();
69
70     set_playmode(); /* sets plname to "wizard" for wizard mode */
71     /* strip role,race,&c suffix; calls askname() if plname[] is empty
72        or holds a generic user name like "player" or "games" */
73     plnamesuffix();
74     /* unlike Unix where the game might be invoked with a script
75        which forces a particular character name for each player
76        using a shared account, we always allow player to rename
77        the character during role/race/&c selection */
78     iflags.renameallowed = TRUE;
79
80     getlock();
81
82 /*
83  * First, try to find and restore a save file for specified character.
84  * We'll return here if new game player_selection() renames the hero.
85  */
86 attempt_restore:
87     if ((fd = restore_saved_game()) >= 0) {
88 #ifdef NEWS
89         if (iflags.news) {
90             display_file(NEWS, FALSE);
91             iflags.news = FALSE; /* in case dorecover() fails */
92         }
93 #endif
94         pline("Restoring save file...");
95         mark_synch(); /* flush output */
96         game_active = 1;
97         if (dorecover(fd)) {
98             resuming = TRUE; /* not starting new game */
99             if (discover)
100                 You("are in non-scoring discovery mode.");
101             if (discover || wizard) {
102                 if (yn("Do you want to keep the save file?") == 'n')
103                     (void) delete_savefile();
104                 else {
105                     nh_compress(fqname(SAVEF, SAVEPREFIX, 0));
106                 }
107             }
108         }
109     }
110
111     if (!resuming) {
112         /* new game:  start by choosing role, race, etc;
113            player might change the hero's name while doing that,
114            in which case we try to restore under the new name
115            and skip selection this time if that didn't succeed */
116         if (!iflags.renameinprogress) {
117             player_selection();
118             if (iflags.renameinprogress) {
119                 /* player has renamed the hero while selecting role;
120                    discard current lock file and create another for
121                    the new character name */
122                 delete_levelfile(0); /* remove empty lock file */
123                 getlock();
124                 goto attempt_restore;
125             }
126         }
127         game_active = 1; /* done with selection, draw active game window */
128         newgame();
129         if (discover)
130             You("are in non-scoring discovery mode.");
131     }
132
133     UndimMenuBar(); /* Yes, this is the place for it (!) */
134
135     moveloop(resuming);
136
137     exit(EXIT_SUCCESS);
138     /*NOTREACHED*/
139     return 0;
140 }
141
142 static OSErr
143 copy_file(short src_vol, long src_dir, short dst_vol, long dst_dir,
144           Str255 fName,
145           pascal OSErr (*opener)(short vRefNum, long dirID,
146                                  ConstStr255Param fileName,
147                                  signed char permission, short *refNum))
148 {
149     short src_ref, dst_ref;
150     OSErr err = (*opener)(src_vol, src_dir, fName, fsRdPerm, &src_ref);
151     if (err == noErr) {
152         err = (*opener)(dst_vol, dst_dir, fName, fsWrPerm, &dst_ref);
153         if (err == noErr) {
154             long file_len;
155             err = GetEOF(src_ref, &file_len);
156             if (err == noErr) {
157                 Handle buf;
158                 long count = MaxBlock();
159                 if (count > file_len)
160                     count = file_len;
161
162                 buf = NewHandle(count);
163                 err = MemError();
164                 if (err == noErr) {
165                     while (count > 0) {
166                         OSErr rd_err = FSRead(src_ref, &count, *buf);
167                         err = FSWrite(dst_ref, &count, *buf);
168                         if (err == noErr)
169                             err = rd_err;
170                         file_len -= count;
171                     }
172                     if (file_len == 0)
173                         err = noErr;
174
175                     DisposeHandle(buf);
176                 }
177             }
178             FSClose(dst_ref);
179         }
180         FSClose(src_ref);
181     }
182
183     return err;
184 }
185
186 static void
187 force_hdelete(short vol, long dir, Str255 fName)
188 {
189     HRstFLock(vol, dir, fName);
190     HDelete(vol, dir, fName);
191 }
192
193 void
194 process_openfile(short src_vol, long src_dir, Str255 fName, OSType ftype)
195 {
196     OSErr err = noErr;
197
198     if (ftype != SAVE_TYPE)
199         return; /* only deal with save files */
200
201     if (src_vol != theDirs.dataRefNum
202         || src_dir != theDirs.dataDirID
203                && CatMove(src_vol, src_dir, fName, theDirs.dataDirID, "\p:")
204                       != noErr) {
205         HCreate(theDirs.dataRefNum, theDirs.dataDirID, fName, MAC_CREATOR,
206                 SAVE_TYPE);
207         err =
208             copy_file(src_vol, src_dir, theDirs.dataRefNum, theDirs.dataDirID,
209                       fName, &HOpen); /* HOpenDF is only there under 7.0 */
210         if (err == noErr)
211             err = copy_file(src_vol, src_dir, theDirs.dataRefNum,
212                             theDirs.dataDirID, fName, &HOpenRF);
213         if (err == noErr)
214             force_hdelete(src_vol, src_dir, fName);
215         else
216             HDelete(theDirs.dataRefNum, theDirs.dataDirID, fName);
217     }
218
219     if (err == noErr) {
220         short ref;
221
222         ref = HOpenResFile(theDirs.dataRefNum, theDirs.dataDirID, fName,
223                            fsRdPerm);
224         if (ref != -1) {
225             Handle name = Get1Resource('STR ', PLAYER_NAME_RES_ID);
226             if (name) {
227                 Str255 save_f_p;
228                 P2C(*(StringHandle) name, plname);
229                 set_savefile_name(TRUE);
230                 C2P(fqname(SAVEF, SAVEPREFIX, 0), save_f_p);
231                 force_hdelete(theDirs.dataRefNum, theDirs.dataDirID,
232                               save_f_p);
233
234                 if (HRename(theDirs.dataRefNum, theDirs.dataDirID, fName,
235                             save_f_p) == noErr)
236                     macFlags.gotOpen = 1;
237             }
238             CloseResFile(ref);
239         }
240     }
241 }
242
243 static void
244 finder_file_request(void)
245 {
246     if (macFlags.hasAE) {
247         /* we're capable of handling Apple Events, so let's see if we have any
248          */
249         EventRecord event;
250         long toWhen = TickCount()
251                       + 20; /* wait a third of a second for all initial AE */
252
253         while (TickCount() < toWhen) {
254             if (WaitNextEvent(highLevelEventMask, &event, 3L, 0)) {
255                 AEProcessAppleEvent(&event);
256                 if (macFlags.gotOpen)
257                     break;
258             }
259         }
260     }
261 #if 0
262 #ifdef MAC68K
263         else {
264                 short finder_msg, file_count;
265                 CountAppFiles(&finder_msg, &file_count);
266                 if (finder_msg == appOpen && file_count == 1) {
267                         OSErr   err;
268                         AppFile src;
269                         FSSpec filespec;
270
271                         GetAppFiles(1, &src);
272                         err = FSMakeFSSpec(src.vRefNum, 0, src.fName, &filespec);
273                         if (err == noErr && src.fType == SAVE_TYPE) {
274                                 process_openfile (filespec.vRefNum, filespec.parID, filespec.name, src.fType);
275                                 if (macFlags.gotOpen)
276                                         ClrAppFiles(1);
277                         }
278                 }
279         }
280 #endif /* MAC68K */
281 #endif /* 0 */
282 }
283
284 /* validate wizard mode if player has requested access to it */
285 boolean
286 authorize_wizard_mode()
287 {
288     /* other ports validate user name or character name here */
289     return TRUE;
290 }
291
292 /*macmain.c*/