Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
/*
2
    SDL - Simple DirectMedia Layer
3
    Copyright (C) 1997-2004 Sam Lantinga
4
 
5
    This library is free software; you can redistribute it and/or
6
    modify it under the terms of the GNU Library General Public
7
    License as published by the Free Software Foundation; either
8
    version 2 of the License, or (at your option) any later version.
9
 
10
    This library is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
    Library General Public License for more details.
14
 
15
    You should have received a copy of the GNU Library General Public
16
    License along with this library; if not, write to the Free
17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 
19
    Sam Lantinga
20
    slouken@libsdl.org
21
*/
22
 
23
#ifdef SAVE_RCSID
24
static char rcsid =
25
 "@(#) $Id: SDL_main.c,v 1.1.1.1 2006/03/17 19:54:28 zicodxx Exp $";
26
#endif
27
 
28
/* This file takes care of command line argument parsing, and stdio redirection
29
   in the MacOS environment.
30
 */
31
 
32
#include <stdio.h>
33
#include <stdlib.h>
34
#include <string.h>
35
#include <ctype.h>
36
#if defined(__APPLE__) && defined(__MACH__)
37
#include <Carbon/Carbon.h>
38
#elif TARGET_API_MAC_CARBON
39
#include <Carbon.h>
40
#else
41
#include <Dialogs.h>
42
#include <Fonts.h>
43
#include <Events.h>
44
#include <Resources.h>
45
#include <Folders.h>
46
#endif
47
 
48
/* Include the SDL main definition header */
49
#include <SDL.h>
50
#include "SDL_main.h"
51
#ifdef main
52
#undef main
53
#endif
54
 
55
/* The standard output files */
56
#define STDOUT_FILE     "stdout.txt"
57
#define STDERR_FILE     "stderr.txt"
58
 
59
#if !defined(__MWERKS__) && !TARGET_API_MAC_CARBON
60
        /* In MPW, the qd global has been removed from the libraries */
61
        QDGlobals qd;
62
#endif
63
 
64
/* Structure for keeping prefs in 1 variable */
65
typedef struct {
66
    Str255  command_line;
67
    Str255  video_driver_name;
68
    Boolean output_to_file;
69
}  PrefsRecord;
70
 
71
/* See if the command key is held down at startup */
72
static Boolean CommandKeyIsDown(void)
73
{
74
        KeyMap  theKeyMap;
75
 
76
        GetKeys(theKeyMap);
77
 
78
        if (((unsigned char *) theKeyMap)[6] & 0x80) {
79
                return(true);
80
        }
81
        return(false);
82
}
83
 
84
/* Parse a command line buffer into arguments */
85
static int ParseCommandLine(char *cmdline, char **argv)
86
{
87
        char *bufp;
88
        int argc;
89
 
90
        argc = 0;
91
        for ( bufp = cmdline; *bufp; ) {
92
                /* Skip leading whitespace */
93
                while ( isspace(*bufp) ) {
94
                        ++bufp;
95
                }
96
                /* Skip over argument */
97
                if ( *bufp == '"' ) {
98
                        ++bufp;
99
                        if ( *bufp ) {
100
                                if ( argv ) {
101
                                        argv[argc] = bufp;
102
                                }
103
                                ++argc;
104
                        }
105
                        /* Skip over word */
106
                        while ( *bufp && (*bufp != '"') ) {
107
                                ++bufp;
108
                        }
109
                } else {
110
                        if ( *bufp ) {
111
                                if ( argv ) {
112
                                        argv[argc] = bufp;
113
                                }
114
                                ++argc;
115
                        }
116
                        /* Skip over word */
117
                        while ( *bufp && ! isspace(*bufp) ) {
118
                                ++bufp;
119
                        }
120
                }
121
                if ( *bufp ) {
122
                        if ( argv ) {
123
                                *bufp = '\0';
124
                        }
125
                        ++bufp;
126
                }
127
        }
128
        if ( argv ) {
129
                argv[argc] = NULL;
130
        }
131
        return(argc);
132
}
133
 
134
/* Remove the output files if there was no output written */
135
static void cleanup_output(void)
136
{
137
        FILE *file;
138
        int empty;
139
 
140
        /* Flush the output in case anything is queued */
141
        fclose(stdout);
142
        fclose(stderr);
143
 
144
        /* See if the files have any output in them */
145
        file = fopen(STDOUT_FILE, "rb");
146
        if ( file ) {
147
                empty = (fgetc(file) == EOF) ? 1 : 0;
148
                fclose(file);
149
                if ( empty ) {
150
                        remove(STDOUT_FILE);
151
                }
152
        }
153
        file = fopen(STDERR_FILE, "rb");
154
        if ( file ) {
155
                empty = (fgetc(file) == EOF) ? 1 : 0;
156
                fclose(file);
157
                if ( empty ) {
158
                        remove(STDERR_FILE);
159
                }
160
        }
161
}
162
 
163
static int getCurrentAppName (StrFileName name) {
164
 
165
    ProcessSerialNumber process;
166
    ProcessInfoRec      process_info;
167
    FSSpec              process_fsp;
168
 
169
    process.highLongOfPSN = 0;
170
    process.lowLongOfPSN  = kCurrentProcess;
171
    process_info.processInfoLength = sizeof (process_info);
172
    process_info.processName    = NULL;
173
    process_info.processAppSpec = &process_fsp;
174
 
175
    if ( noErr != GetProcessInformation (&process, &process_info) )
176
       return 0;
177
 
178
    memcpy (name, process_fsp.name, process_fsp.name[0] + 1);
179
    return 1;
180
}
181
 
182
static int getPrefsFile (FSSpec *prefs_fsp, int create) {
183
 
184
    /* The prefs file name is the application name, possibly truncated, */
185
    /* plus " Preferences */
186
 
187
    #define  SUFFIX   " Preferences"
188
    #define  MAX_NAME 19             /* 31 - strlen (SUFFIX) */
189
 
190
    short  volume_ref_number;
191
    long   directory_id;
192
    StrFileName  prefs_name;
193
    StrFileName  app_name;
194
 
195
    /* Get Preferences folder - works with Multiple Users */
196
    if ( noErr != FindFolder ( kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder,
197
                               &volume_ref_number, &directory_id) )
198
        exit (-1);
199
 
200
    if ( ! getCurrentAppName (app_name) )
201
        exit (-1);
202
 
203
    /* Truncate if name is too long */
204
    if (app_name[0] > MAX_NAME )
205
        app_name[0] = MAX_NAME;
206
 
207
    memcpy (prefs_name + 1, app_name + 1, app_name[0]);    
208
    memcpy (prefs_name + app_name[0] + 1, SUFFIX, strlen (SUFFIX));
209
    prefs_name[0] = app_name[0] + strlen (SUFFIX);
210
 
211
    /* Make the file spec for prefs file */
212
    if ( noErr != FSMakeFSSpec (volume_ref_number, directory_id, prefs_name, prefs_fsp) )
213
        if ( !create )
214
            return 0;
215
        else {
216
            /* Create the prefs file */
217
            memcpy (prefs_fsp->name, prefs_name, prefs_name[0] + 1);
218
            prefs_fsp->parID   = directory_id;
219
            prefs_fsp->vRefNum = volume_ref_number;
220
 
221
            FSpCreateResFile (prefs_fsp, '????', 'pref', 0);
222
 
223
            if ( noErr != ResError () )
224
                return 0;
225
        }
226
 
227
    return 1;
228
}
229
 
230
static int readPrefsResource (PrefsRecord *prefs) {
231
 
232
    Handle prefs_handle;
233
 
234
    prefs_handle = Get1Resource( 'CLne', 128 );
235
 
236
        if (prefs_handle != NULL) {
237
                int offset = 0;
238
 
239
                HLock(prefs_handle);
240
 
241
                /* Get command line string */  
242
                memcpy (prefs->command_line, *prefs_handle, (*prefs_handle)[0]+1);
243
 
244
                /* Get video driver name */
245
                offset += (*prefs_handle)[0] + 1;      
246
                memcpy (prefs->video_driver_name, *prefs_handle + offset, (*prefs_handle)[offset] + 1);        
247
 
248
                /* Get save-to-file option (1 or 0) */
249
                offset += (*prefs_handle)[offset] + 1;
250
                prefs->output_to_file = (*prefs_handle)[offset];
251
 
252
                ReleaseResource( prefs_handle );
253
 
254
        return ResError() == noErr;
255
    }
256
 
257
    return 0;
258
}
259
 
260
static int writePrefsResource (PrefsRecord *prefs, short resource_file) {
261
 
262
    Handle prefs_handle;
263
 
264
    UseResFile (resource_file);
265
 
266
    prefs_handle = Get1Resource ( 'CLne', 128 );
267
    if (prefs_handle != NULL)
268
        RemoveResource (prefs_handle);
269
 
270
    prefs_handle = NewHandle ( prefs->command_line[0] + prefs->video_driver_name[0] + 4 );
271
    if (prefs_handle != NULL) {
272
 
273
        int offset;
274
 
275
        HLock (prefs_handle);
276
 
277
        /* Command line text */
278
        offset = 0;
279
        memcpy (*prefs_handle, prefs->command_line, prefs->command_line[0] + 1);
280
 
281
        /* Video driver name */
282
        offset += prefs->command_line[0] + 1;
283
        memcpy (*prefs_handle + offset, prefs->video_driver_name, prefs->video_driver_name[0] + 1);
284
 
285
        /* Output-to-file option */
286
        offset += prefs->video_driver_name[0] + 1;
287
        *( *((char**)prefs_handle) + offset)     = (char)prefs->output_to_file;
288
        *( *((char**)prefs_handle) + offset + 1) = 0;
289
 
290
        AddResource   (prefs_handle, 'CLne', 128, "\pCommand Line");
291
        WriteResource (prefs_handle);
292
        UpdateResFile (resource_file);
293
        DisposeHandle (prefs_handle);
294
 
295
        return ResError() == noErr;
296
    }
297
 
298
    return 0;
299
}
300
 
301
static int readPreferences (PrefsRecord *prefs) {
302
 
303
    int    no_error = 1;
304
    FSSpec prefs_fsp;
305
 
306
    /* Check for prefs file first */
307
    if ( getPrefsFile (&prefs_fsp, 0) ) {
308
 
309
        short  prefs_resource;
310
 
311
        prefs_resource = FSpOpenResFile (&prefs_fsp, fsRdPerm);
312
        if ( prefs_resource == -1 ) /* this shouldn't happen, but... */
313
            return 0;
314
 
315
        UseResFile   (prefs_resource);
316
        no_error = readPrefsResource (prefs);    
317
        CloseResFile (prefs_resource);
318
    }
319
 
320
    /* Fall back to application's resource fork (reading only, so this is safe) */
321
    else {
322
 
323
          no_error = readPrefsResource (prefs);
324
     }
325
 
326
    return no_error;
327
}
328
 
329
static int writePreferences (PrefsRecord *prefs) {
330
 
331
    int    no_error = 1;
332
    FSSpec prefs_fsp;
333
 
334
    /* Get prefs file, create if it doesn't exist */
335
    if ( getPrefsFile (&prefs_fsp, 1) ) {
336
 
337
        short  prefs_resource;
338
 
339
        prefs_resource = FSpOpenResFile (&prefs_fsp, fsRdWrPerm);
340
        if (prefs_resource == -1)
341
            return 0;
342
        no_error = writePrefsResource (prefs, prefs_resource);
343
        CloseResFile (prefs_resource);
344
    }
345
 
346
    return no_error;
347
}
348
 
349
/* This is where execution begins */
350
int main(int argc, char *argv[])
351
{
352
 
353
#pragma unused(argc, argv)
354
 
355
#define DEFAULT_ARGS "\p"                /* pascal string for default args */
356
#define DEFAULT_VIDEO_DRIVER "\ptoolbox" /* pascal string for default video driver name */      
357
#define DEFAULT_OUTPUT_TO_FILE 1         /* 1 == output to file, 0 == no output */
358
 
359
#define VIDEO_ID_DRAWSPROCKET 1          /* these correspond to popup menu choices */
360
#define VIDEO_ID_TOOLBOX      2
361
 
362
    PrefsRecord prefs = { DEFAULT_ARGS, DEFAULT_VIDEO_DRIVER, DEFAULT_OUTPUT_TO_FILE };
363
 
364
        int     nargs;
365
        char   **args;
366
        char   *commandLine;
367
 
368
        StrFileName  appNameText;
369
        int     videodriver     = VIDEO_ID_TOOLBOX;
370
    int     settingsChanged = 0;
371
 
372
    long        i;
373
 
374
        /* Kyle's SDL command-line dialog code ... */
375
#if !TARGET_API_MAC_CARBON
376
        InitGraf    (&qd.thePort);
377
        InitFonts   ();
378
        InitWindows ();
379
        InitMenus   ();
380
        InitDialogs (nil);
381
#endif
382
        InitCursor ();
383
        FlushEvents(everyEvent,0);
384
#if !TARGET_API_MAC_CARBON
385
        MaxApplZone ();
386
#endif
387
        MoreMasters ();
388
        MoreMasters ();
389
#if 0
390
        /* Intialize SDL, and put up a dialog if we fail */
391
        if ( SDL_Init (0) < 0 ) {
392
 
393
#define kErr_OK         1
394
#define kErr_Text       2
395
 
396
        DialogPtr errorDialog;
397
        short     dummyType;
398
        Rect      dummyRect;
399
            Handle    dummyHandle;
400
            short     itemHit;
401
 
402
                errorDialog = GetNewDialog (1001, nil, (WindowPtr)-1);
403
                DrawDialog (errorDialog);
404
 
405
                GetDialogItem (errorDialog, kErr_Text, &dummyType, &dummyHandle, &dummyRect);
406
                SetDialogItemText (dummyHandle, "\pError Initializing SDL");
407
 
408
                SetPort (errorDialog);
409
                do {
410
                        ModalDialog (nil, &itemHit);
411
                } while (itemHit != kErr_OK);
412
 
413
                DisposeDialog (errorDialog);
414
                exit (-1);
415
        }
416
        atexit(cleanup_output);
417
        atexit(SDL_Quit);
418
#endif
419
 
420
/* Set up SDL's QuickDraw environment  */
421
#if !TARGET_API_MAC_CARBON
422
        SDL_InitQuickDraw(&qd);
423
#endif
424
 
425
         if ( readPreferences (&prefs) ) {
426
 
427
        if (memcmp (prefs.video_driver_name+1, "DSp", 3) == 0)
428
            videodriver = 1;
429
        else if (memcmp (prefs.video_driver_name+1, "toolbox", 7) == 0)
430
            videodriver = 2;
431
         }
432
 
433
        if ( CommandKeyIsDown() ) {
434
 
435
#define kCL_OK          1
436
#define kCL_Cancel      2
437
#define kCL_Text        3
438
#define kCL_File        4
439
#define kCL_Video   6
440
 
441
        DialogPtr commandDialog;
442
        short     dummyType;
443
        Rect      dummyRect;
444
        Handle    dummyHandle;
445
        short     itemHit;
446
 
447
        /* Assume that they will change settings, rather than do exhaustive check */
448
        settingsChanged = 1;
449
 
450
        /* Create dialog and display it */
451
        commandDialog = GetNewDialog (1000, nil, (WindowPtr)-1);
452
        SetPortDialogPort (commandDialog);
453
 
454
        /* Setup controls */
455
        GetDialogItem   (commandDialog, kCL_File, &dummyType, &dummyHandle, &dummyRect); /* MJS */
456
        SetControlValue ((ControlHandle)dummyHandle, prefs.output_to_file );
457
 
458
        GetDialogItem     (commandDialog, kCL_Text, &dummyType, &dummyHandle, &dummyRect);
459
        SetDialogItemText (dummyHandle, prefs.command_line);
460
 
461
        GetDialogItem   (commandDialog, kCL_Video, &dummyType, &dummyHandle, &dummyRect);
462
        SetControlValue ((ControlRef)dummyHandle, videodriver);
463
 
464
        SetDialogDefaultItem (commandDialog, kCL_OK);
465
        SetDialogCancelItem  (commandDialog, kCL_Cancel);
466
 
467
        do {
468
 
469
                ModalDialog(nil, &itemHit); /* wait for user response */
470
 
471
            /* Toggle command-line output checkbox */  
472
                if ( itemHit == kCL_File ) {
473
                        GetDialogItem(commandDialog, kCL_File, &dummyType, &dummyHandle, &dummyRect); /* MJS */
474
                        SetControlValue((ControlHandle)dummyHandle, !GetControlValue((ControlHandle)dummyHandle) );
475
                }
476
 
477
        } while (itemHit != kCL_OK && itemHit != kCL_Cancel);
478
 
479
        /* Get control values, even if they did not change */
480
        GetDialogItem     (commandDialog, kCL_Text, &dummyType, &dummyHandle, &dummyRect); /* MJS */
481
        GetDialogItemText (dummyHandle, prefs.command_line);
482
 
483
        GetDialogItem (commandDialog, kCL_File, &dummyType, &dummyHandle, &dummyRect); /* MJS */
484
        prefs.output_to_file = GetControlValue ((ControlHandle)dummyHandle);
485
 
486
        GetDialogItem (commandDialog, kCL_Video, &dummyType, &dummyHandle, &dummyRect);
487
        videodriver = GetControlValue ((ControlRef)dummyHandle);
488
 
489
        DisposeDialog (commandDialog);
490
 
491
        if (itemHit == kCL_Cancel ) {
492
                exit (0);
493
        }
494
        }
495
 
496
    /* Set pseudo-environment variables for video driver, update prefs */
497
        switch ( videodriver ) {
498
           case VIDEO_ID_DRAWSPROCKET:
499
              SDL_putenv ("SDL_VIDEODRIVER=DSp");
500
              memcpy (prefs.video_driver_name, "\pDSp", 4);
501
              break;
502
           case VIDEO_ID_TOOLBOX:
503
              SDL_putenv ("SDL_VIDEODRIVER=toolbox");
504
              memcpy (prefs.video_driver_name, "\ptoolbox", 8);
505
              break;
506
        }
507
    /* Redirect standard I/O to files */
508
        if ( prefs.output_to_file ) {
509
                freopen (STDOUT_FILE, "w", stdout);
510
                freopen (STDERR_FILE, "w", stderr);
511
        } else {
512
                fclose (stdout);
513
                fclose (stderr);
514
        }
515
 
516
    if (settingsChanged) {
517
        /* Save the prefs, even if they might not have changed (but probably did) */
518
        if ( ! writePreferences (&prefs) )
519
            fprintf (stderr, "WARNING: Could not save preferences!\n");
520
    }
521
 
522
    getCurrentAppName (appNameText); /* check for error here ? */
523
 
524
    commandLine = (char*) malloc (appNameText[0] + prefs.command_line[0] + 2);
525
    if ( commandLine == NULL ) {
526
       exit(-1);
527
    }
528
 
529
    /* Rather than rewrite ParseCommandLine method, let's replace  */
530
    /* any spaces in application name with underscores,            */
531
    /* so that the app name is only 1 argument                     */  
532
    for (i = 1; i < 1+appNameText[0]; i++)
533
        if ( appNameText[i] == ' ' ) appNameText[i] = '_';
534
 
535
    /* Copy app name & full command text to command-line C-string */      
536
    memcpy (commandLine, appNameText + 1, appNameText[0]);
537
    commandLine[appNameText[0]] = ' ';
538
    memcpy (commandLine + appNameText[0] + 1, prefs.command_line + 1, prefs.command_line[0]);
539
    commandLine[ appNameText[0] + 1 + prefs.command_line[0] ] = '\0';
540
 
541
    /* Parse C-string into argv and argc */
542
    nargs = ParseCommandLine (commandLine, NULL);
543
    args = (char **)malloc((nargs+1)*(sizeof *args));
544
    if ( args == NULL ) {
545
                exit(-1);
546
        }
547
        ParseCommandLine (commandLine, args);
548
 
549
        /* Run the main application code */
550
        SDL_main(nargs, args);
551
        free (args);
552
        free (commandLine);
553
 
554
        /* Remove useless stdout.txt and stderr.txt */
555
        cleanup_output ();
556
 
557
        /* Exit cleanly, calling atexit() functions */
558
        exit (0);    
559
 
560
        /* Never reached, but keeps the compiler quiet */
561
        return (0);
562
}