src/main/macos/SDL_main.c
author Sam Lantinga
Sun, 21 Sep 2003 18:32:04 +0000
changeset 720 f90d80d68071
parent 297 f6ffac90895c
child 769 b8d311d90021
permissions -rw-r--r--
N Sep 17 8791 Sam Lantinga Re: tks source released
Date: Sun, 07 Sep 2003 02:51:58 +0200
From: Stephane Marchesin
Subject: [SDL] Two little patches

Compiling SDL with a recent gcc (gcc 3.3.1, 3.3 doesn't have this
behaviour) gives some nasty warnings :

SDL_blit_A.c: In function `BlitRGBtoRGBSurfaceAlpha128MMX':
SDL_blit_A.c:223: warning: integer constant is too large for "long" type
SDL_blit_A.c:225: warning: integer constant is too large for "long" type
SDL_blit_A.c:227: warning: integer constant is too large for "long" type
[...]

The first attached patch (longlongfix.patch) tells gcc to really treat
those constants as unsigned long long and not long.

The second patch (nasinclude.patch) fixes an include problem I had while
compiling nas audio : when the <audio/audiolib.h> file lies in
/usr/X11R6/include, a -I/usr/X11R6/include option is needed or the file
isn't found.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  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$";
    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 TARGET_API_MAC_CARBON
    37 #include <Carbon.h>
    38 #else
    39 #include <Dialogs.h>
    40 #include <Fonts.h>
    41 #include <Events.h>
    42 #include <Resources.h>
    43 #include <Folders.h>
    44 #endif
    45 
    46 /* Include the SDL main definition header */
    47 #include "SDL.h"
    48 #include "SDL_main.h"
    49 #ifdef main
    50 #undef main
    51 #endif
    52 
    53 /* The standard output files */
    54 #define STDOUT_FILE	"stdout.txt"
    55 #define STDERR_FILE	"stderr.txt"
    56 
    57 #if !defined(__MWERKS__) && !TARGET_API_MAC_CARBON
    58 	/* In MPW, the qd global has been removed from the libraries */
    59 	QDGlobals qd;
    60 #endif
    61 
    62 /* Structure for keeping prefs in 1 variable */
    63 typedef struct {
    64     Str255  command_line;
    65     Str255  video_driver_name;
    66     Boolean output_to_file;
    67 }  PrefsRecord;
    68 
    69 /* See if the command key is held down at startup */
    70 static Boolean CommandKeyIsDown(void)
    71 {
    72 	KeyMap  theKeyMap;
    73 
    74 	GetKeys(theKeyMap);
    75 
    76 	if (((unsigned char *) theKeyMap)[6] & 0x80) {
    77 		return(true);
    78 	}
    79 	return(false);
    80 }
    81 
    82 /* Parse a command line buffer into arguments */
    83 static int ParseCommandLine(char *cmdline, char **argv)
    84 {
    85 	char *bufp;
    86 	int argc;
    87 
    88 	argc = 0;
    89 	for ( bufp = cmdline; *bufp; ) {
    90 		/* Skip leading whitespace */
    91 		while ( isspace(*bufp) ) {
    92 			++bufp;
    93 		}
    94 		/* Skip over argument */
    95 		if ( *bufp == '"' ) {
    96 			++bufp;
    97 			if ( *bufp ) {
    98 				if ( argv ) {
    99 					argv[argc] = bufp;
   100 				}
   101 				++argc;
   102 			}
   103 			/* Skip over word */
   104 			while ( *bufp && (*bufp != '"') ) {
   105 				++bufp;
   106 			}
   107 		} else {
   108 			if ( *bufp ) {
   109 				if ( argv ) {
   110 					argv[argc] = bufp;
   111 				}
   112 				++argc;
   113 			}
   114 			/* Skip over word */
   115 			while ( *bufp && ! isspace(*bufp) ) {
   116 				++bufp;
   117 			}
   118 		}
   119 		if ( *bufp ) {
   120 			if ( argv ) {
   121 				*bufp = '\0';
   122 			}
   123 			++bufp;
   124 		}
   125 	}
   126 	if ( argv ) {
   127 		argv[argc] = NULL;
   128 	}
   129 	return(argc);
   130 }
   131 
   132 /* Remove the output files if there was no output written */
   133 static void cleanup_output(void)
   134 {
   135 	FILE *file;
   136 	int empty;
   137 
   138 	/* Flush the output in case anything is queued */
   139 	fclose(stdout);
   140 	fclose(stderr);
   141 
   142 	/* See if the files have any output in them */
   143 	file = fopen(STDOUT_FILE, "rb");
   144 	if ( file ) {
   145 		empty = (fgetc(file) == EOF) ? 1 : 0;
   146 		fclose(file);
   147 		if ( empty ) {
   148 			remove(STDOUT_FILE);
   149 		}
   150 	}
   151 	file = fopen(STDERR_FILE, "rb");
   152 	if ( file ) {
   153 		empty = (fgetc(file) == EOF) ? 1 : 0;
   154 		fclose(file);
   155 		if ( empty ) {
   156 			remove(STDERR_FILE);
   157 		}
   158 	}
   159 }
   160 
   161 static int getCurrentAppName (StrFileName name) {
   162 	
   163     ProcessSerialNumber process;
   164     ProcessInfoRec      process_info;
   165     FSSpec              process_fsp;
   166     
   167     process.highLongOfPSN = 0;
   168     process.lowLongOfPSN  = kCurrentProcess;
   169     process_info.processInfoLength = sizeof (process_info);
   170     process_info.processName    = NULL;
   171     process_info.processAppSpec = &process_fsp;
   172     
   173     if ( noErr != GetProcessInformation (&process, &process_info) )
   174        return 0;
   175     
   176     memcpy (name, process_fsp.name, process_fsp.name[0] + 1);
   177     return 1;
   178 }
   179 
   180 static int getPrefsFile (FSSpec *prefs_fsp, int create) {
   181 
   182     /* The prefs file name is the application name, possibly truncated, */
   183     /* plus " Preferences */
   184     
   185     #define  SUFFIX   " Preferences"
   186     #define  MAX_NAME 19             /* 31 - strlen (SUFFIX) */
   187     
   188     short  volume_ref_number;
   189     long   directory_id;
   190     StrFileName  prefs_name;
   191     StrFileName  app_name;
   192     
   193     /* Get Preferences folder - works with Multiple Users */
   194     if ( noErr != FindFolder ( kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder,
   195                                &volume_ref_number, &directory_id) )
   196         exit (-1);
   197     
   198     if ( ! getCurrentAppName (app_name) )
   199         exit (-1);
   200     
   201     /* Truncate if name is too long */
   202     if (app_name[0] > MAX_NAME )
   203         app_name[0] = MAX_NAME;
   204         
   205     memcpy (prefs_name + 1, app_name + 1, app_name[0]);    
   206     memcpy (prefs_name + app_name[0] + 1, SUFFIX, strlen (SUFFIX));
   207     prefs_name[0] = app_name[0] + strlen (SUFFIX);
   208    
   209     /* Make the file spec for prefs file */
   210     if ( noErr != FSMakeFSSpec (volume_ref_number, directory_id, prefs_name, prefs_fsp) )
   211         if ( !create )
   212             return 0;
   213         else {
   214             /* Create the prefs file */
   215             memcpy (prefs_fsp->name, prefs_name, prefs_name[0] + 1);
   216             prefs_fsp->parID   = directory_id;
   217             prefs_fsp->vRefNum = volume_ref_number;
   218                 
   219             FSpCreateResFile (prefs_fsp, '????', 'pref', 0);
   220             
   221             if ( noErr != ResError () )
   222                 return 0;
   223         }
   224       
   225     return 1;
   226 }
   227 
   228 static int readPrefsResource (PrefsRecord *prefs) {
   229     
   230     Handle prefs_handle;
   231     
   232     prefs_handle = Get1Resource( 'CLne', 128 );
   233 
   234 	if (prefs_handle != NULL) {
   235 		int offset = 0;
   236 		int j      = 0;
   237 		
   238 		HLock(prefs_handle);
   239 		
   240 		/* Get command line string */	
   241 		memcpy (prefs->command_line, *prefs_handle, (*prefs_handle)[0]+1);
   242 
   243 		/* Get video driver name */
   244 		offset += (*prefs_handle)[0] + 1;	
   245 		memcpy (prefs->video_driver_name, *prefs_handle + offset, (*prefs_handle)[offset] + 1);		
   246 		
   247 		/* Get save-to-file option (1 or 0) */
   248 		offset += (*prefs_handle)[offset] + 1;
   249 		prefs->output_to_file = (*prefs_handle)[offset];
   250 		
   251 		ReleaseResource( prefs_handle );
   252     
   253         return ResError() == noErr;
   254     }
   255 
   256     return 0;
   257 }
   258 
   259 static int writePrefsResource (PrefsRecord *prefs, short resource_file) {
   260 
   261     Handle prefs_handle;
   262     
   263     UseResFile (resource_file);
   264     
   265     prefs_handle = Get1Resource ( 'CLne', 128 );
   266     if (prefs_handle != NULL)
   267         RemoveResource (prefs_handle);
   268     
   269     prefs_handle = NewHandle ( prefs->command_line[0] + prefs->video_driver_name[0] + 4 );
   270     if (prefs_handle != NULL) {
   271     
   272         int offset;
   273         
   274         HLock (prefs_handle);
   275         
   276         /* Command line text */
   277         offset = 0;
   278         memcpy (*prefs_handle, prefs->command_line, prefs->command_line[0] + 1);
   279         
   280         /* Video driver name */
   281         offset += prefs->command_line[0] + 1;
   282         memcpy (*prefs_handle + offset, prefs->video_driver_name, prefs->video_driver_name[0] + 1);
   283         
   284         /* Output-to-file option */
   285         offset += prefs->video_driver_name[0] + 1;
   286         *( *((char**)prefs_handle) + offset)     = (char)prefs->output_to_file;
   287         *( *((char**)prefs_handle) + offset + 1) = 0;
   288               
   289         AddResource   (prefs_handle, 'CLne', 128, "\pCommand Line");
   290         WriteResource (prefs_handle);
   291         UpdateResFile (resource_file);
   292         DisposeHandle (prefs_handle);
   293         
   294         return ResError() == noErr;
   295     }
   296     
   297     return 0;
   298 }
   299 
   300 static int readPreferences (PrefsRecord *prefs) {
   301 
   302     int    no_error = 1;
   303     FSSpec prefs_fsp;
   304 
   305     /* Check for prefs file first */
   306     if ( getPrefsFile (&prefs_fsp, 0) ) {
   307     
   308         short  prefs_resource;
   309         
   310         prefs_resource = FSpOpenResFile (&prefs_fsp, fsRdPerm);
   311         if ( prefs_resource == -1 ) /* this shouldn't happen, but... */
   312             return 0;
   313     
   314         UseResFile   (prefs_resource);
   315         no_error = readPrefsResource (prefs);     
   316         CloseResFile (prefs_resource);
   317     }
   318     
   319     /* Fall back to application's resource fork (reading only, so this is safe) */
   320     else {
   321     
   322           no_error = readPrefsResource (prefs);
   323      }
   324 
   325     return no_error;
   326 }
   327 
   328 static int writePreferences (PrefsRecord *prefs) {
   329     
   330     int    no_error = 1;
   331     FSSpec prefs_fsp;
   332     
   333     /* Get prefs file, create if it doesn't exist */
   334     if ( getPrefsFile (&prefs_fsp, 1) ) {
   335     
   336         short  prefs_resource;
   337         
   338         prefs_resource = FSpOpenResFile (&prefs_fsp, fsRdWrPerm);
   339         if (prefs_resource == -1)
   340             return 0;
   341         no_error = writePrefsResource (prefs, prefs_resource);
   342         CloseResFile (prefs_resource);
   343     }
   344     
   345     return no_error;
   346 }
   347 
   348 /* This is where execution begins */
   349 int main(int argc, char *argv[])
   350 {
   351 
   352 #pragma unused(argc, argv)
   353 	
   354 #define DEFAULT_ARGS "\p"                /* pascal string for default args */
   355 #define DEFAULT_VIDEO_DRIVER "\ptoolbox" /* pascal string for default video driver name */	
   356 #define DEFAULT_OUTPUT_TO_FILE 1         /* 1 == output to file, 0 == no output */
   357 
   358 #define VIDEO_ID_DRAWSPROCKET 1          /* these correspond to popup menu choices */
   359 #define VIDEO_ID_TOOLBOX      2
   360 
   361     PrefsRecord prefs = { DEFAULT_ARGS, DEFAULT_VIDEO_DRIVER, DEFAULT_OUTPUT_TO_FILE }; 
   362 	
   363 	int     nargs;
   364 	char   **args;
   365 	char   *commandLine;
   366 	
   367 	StrFileName  appNameText;
   368 	int     videodriver     = VIDEO_ID_TOOLBOX;
   369     int     settingsChanged = 0;
   370     
   371     long	i;
   372 
   373 	/* Kyle's SDL command-line dialog code ... */
   374 #if !TARGET_API_MAC_CARBON
   375 	InitGraf    (&qd.thePort);
   376 	InitFonts   ();
   377 	InitWindows ();
   378 	InitMenus   ();
   379 	InitDialogs (nil);
   380 #endif
   381 	InitCursor ();
   382 	FlushEvents(everyEvent,0);
   383 #if !TARGET_API_MAC_CARBON
   384 	MaxApplZone ();
   385 #endif
   386 	MoreMasters ();
   387 	MoreMasters ();
   388 #if 0
   389 	/* Intialize SDL, and put up a dialog if we fail */
   390 	if ( SDL_Init (0) < 0 ) {
   391 
   392 #define kErr_OK		1
   393 #define kErr_Text	2
   394 
   395         DialogPtr errorDialog;
   396         short	  dummyType;
   397     	Rect	  dummyRect;
   398 	    Handle    dummyHandle;
   399 	    short     itemHit;
   400 	
   401 		errorDialog = GetNewDialog (1001, nil, (WindowPtr)-1);
   402 		DrawDialog (errorDialog);
   403 		
   404 		GetDialogItem (errorDialog, kErr_Text, &dummyType, &dummyHandle, &dummyRect);
   405 		SetDialogItemText (dummyHandle, "\pError Initializing SDL");
   406 		
   407 		SetPort (errorDialog);
   408 		do {
   409 			ModalDialog (nil, &itemHit);
   410 		} while (itemHit != kErr_OK);
   411 		
   412 		DisposeDialog (errorDialog);
   413 		exit (-1);
   414 	}
   415 	atexit(cleanup_output);
   416 	atexit(SDL_Quit);
   417 #endif
   418 
   419 /* Set up SDL's QuickDraw environment  */
   420 #if !TARGET_API_MAC_CARBON
   421 	SDL_InitQuickDraw(&qd);
   422 #endif
   423 
   424 	 if ( readPreferences (&prefs) ) {
   425 		
   426         if (memcmp (prefs.video_driver_name+1, "DSp", 3) == 0)
   427             videodriver = 1;
   428         else if (memcmp (prefs.video_driver_name+1, "toolbox", 7) == 0)
   429             videodriver = 2;
   430 	 }
   431 	 	
   432 	if ( CommandKeyIsDown() ) {
   433 
   434 #define kCL_OK		1
   435 #define kCL_Cancel	2
   436 #define kCL_Text	3
   437 #define kCL_File	4
   438 #define kCL_Video   6
   439        
   440         DialogPtr commandDialog;
   441         short	  dummyType;
   442         Rect	  dummyRect;
   443         Handle    dummyHandle;
   444         short     itemHit;
   445 
   446         /* Assume that they will change settings, rather than do exhaustive check */
   447         settingsChanged = 1;
   448         
   449         /* Create dialog and display it */
   450         commandDialog = GetNewDialog (1000, nil, (DialogPtr)-1);
   451         SetPort (commandDialog);
   452             
   453         /* Setup controls */
   454         GetDialogItem   (commandDialog, kCL_File, &dummyType, &dummyHandle, &dummyRect); /* MJS */
   455         SetControlValue ((ControlHandle)dummyHandle, prefs.output_to_file );
   456 
   457         GetDialogItem     (commandDialog, kCL_Text, &dummyType, &dummyHandle, &dummyRect);
   458         SetDialogItemText (dummyHandle, prefs.command_line);
   459 
   460         GetDialogItem   (commandDialog, kCL_Video, &dummyType, &dummyHandle, &dummyRect);
   461         SetControlValue ((ControlRef)dummyHandle, videodriver);
   462 
   463         SetDialogDefaultItem (commandDialog, kCL_OK);
   464         SetDialogCancelItem  (commandDialog, kCL_Cancel);
   465 
   466         do {
   467         		
   468         	ModalDialog(nil, &itemHit); /* wait for user response */
   469             
   470             /* Toggle command-line output checkbox */	
   471         	if ( itemHit == kCL_File ) {
   472         		GetDialogItem(commandDialog, kCL_File, &dummyType, &dummyHandle, &dummyRect); /* MJS */
   473         		SetControlValue((ControlHandle)dummyHandle, !GetControlValue((ControlHandle)dummyHandle) );
   474         	}
   475 
   476         } while (itemHit != kCL_OK && itemHit != kCL_Cancel);
   477 
   478         /* Get control values, even if they did not change */
   479         GetDialogItem     (commandDialog, kCL_Text, &dummyType, &dummyHandle, &dummyRect); /* MJS */
   480         GetDialogItemText (dummyHandle, prefs.command_line);
   481 
   482         GetDialogItem (commandDialog, kCL_File, &dummyType, &dummyHandle, &dummyRect); /* MJS */
   483         prefs.output_to_file = GetControlValue ((ControlHandle)dummyHandle);
   484 
   485         GetDialogItem (commandDialog, kCL_Video, &dummyType, &dummyHandle, &dummyRect);
   486         videodriver = GetControlValue ((ControlRef)dummyHandle);
   487 
   488         DisposeDialog (commandDialog);
   489 
   490         if (itemHit == kCL_Cancel ) {
   491         	exit (0);
   492         }
   493 	}
   494     
   495     /* Set pseudo-environment variables for video driver, update prefs */
   496 	switch ( videodriver ) {
   497 	   case VIDEO_ID_DRAWSPROCKET: 
   498 	      putenv ("SDL_VIDEODRIVER=DSp");
   499 	      memcpy (prefs.video_driver_name, "\pDSp", 4);
   500 	      break;
   501 	   case VIDEO_ID_TOOLBOX:
   502 	      putenv ("SDL_VIDEODRIVER=toolbox");
   503 	      memcpy (prefs.video_driver_name, "\ptoolbox", 8);
   504 	      break;
   505 	}
   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 }