Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
WatchMe.c
////////// |
// |
// File: WatchMe.c |
// |
// Contains: Application-specific code for WatchMe shell. |
// |
// Written by: Tim Monroe |
// |
// Copyright: © 1998 by Apple Computer, Inc., all rights reserved. |
// |
// Change History (most recent first): |
// |
// <4> 07/30/98 rtm added WatchMe_GetLaunchVolumeName |
// <3> 07/28/98 rtm some clean-up; added WatchMe_EncodeURL |
// <2> 07/25/98 rtm further enhancements; everything working pretty well now |
// <1> 07/23/98 rtm first file |
// |
// Currently, the movie controller knows how to handle absolute URLs but not relative ones. |
// Here our job is to convert a relative URL into an absolute one. By "relative" we mean that |
// a URL is relative to the location of the movie file. |
// |
////////// |
// header files |
#include "WatchMe.h" |
////////// |
// |
// WatchMe_ConvertRelativeToAbsoluteURL |
// Convert a relative URL to an absolute URL. |
// |
// On entry, theURLHandle is a handle to a block of memory that contains a URL, |
// either absolute or relative. If it's absolute, we don't do anything. If it's |
// relative, we convert the URL to an absolute one and return a handle to that |
// URL in theURLHandle. |
// |
// On entry, theRefCon is a handle to a window object record. We use it only to |
// obtain the full pathname of the movie file. You could simplify this function |
// if you passed the full pathname as a parameter. |
// |
////////// |
void WatchMe_ConvertRelativeToAbsoluteURL (Handle theURLHandle, long theRefCon) |
{ |
WindowObject myWindowObject = (WindowObject)theRefCon; |
char *myMovieFilePath = NULL; |
char *myMovieFolderURL = NULL; |
char *myGivenURL = NULL; |
char myAbsoluteURL[MAX_PATH]; |
Size mySize = 0; |
int myIndex, myCount; |
////////// |
// |
// copy the URL passed to this function into a C string |
// |
////////// |
mySize = GetHandleSize(theURLHandle); |
if (mySize <= 0) |
goto bail; |
myGivenURL = malloc(mySize + 1); |
if (myGivenURL == NULL) |
goto bail; |
BlockMove(*theURLHandle, myGivenURL, mySize); |
myGivenURL[mySize] = '\0'; |
////////// |
// |
// if myGivenURL is already absolute, just return |
// |
////////// |
if (WatchMe_IsAbsoluteURL(myGivenURL)) |
goto bail; |
////////// |
// |
// get the full pathname of the movie file |
// |
////////// |
if (myWindowObject == NULL) |
goto bail; |
myMovieFilePath = WatchMe_FSSpecToFullPath(&(**myWindowObject).fFileFSSpec); |
if (myMovieFilePath == NULL) |
goto bail; |
////////// |
// |
// convert the full pathname of the movie file into a URL to the folder enclosing the movie file |
// |
////////// |
myMovieFolderURL = WatchMe_FullPathToURL(myMovieFilePath); |
if (myMovieFolderURL == NULL) |
goto bail; |
// strip off the file name, to get the folder name |
myIndex = strlen(myMovieFolderURL) - 1; |
while (myMovieFolderURL[myIndex] != kWM_URLSeparator) |
myIndex--; |
myMovieFolderURL[myIndex] = '\0'; |
////////// |
// |
// if we successfully arrived here, myGivenURL is a URL specified relative to myMovieFolderURL |
// |
// there are three cases to consider: |
// (1) myGivenURL is a file in a folder below the folder myMovieFolderURL |
// (2) myGivenURL is a file in a folder above the folder myMovieFolderURL |
// (3) myGivenURL is a file in the folder myMovieFolderURL |
// |
////////// |
myAbsoluteURL[0] = '\0'; |
if ((myGivenURL[0] == '.') && (myGivenURL[1] == kWM_URLSeparator)) { |
////////// |
// |
// (1) myGivenURL is a file in a folder below the folder myMovieFolderURL |
// |
// we assume that myGivenURL begins with the string "./" and that the remainder |
// of myGivenURL is a partial URL path with no further "./" or "../" constructs |
// |
////////// |
// take all of the existing myMovieFolderURL |
strcat(myAbsoluteURL, myMovieFolderURL); |
// strip off the initial '.' and append the rest of myGivenURL to myAbsoluteURL |
strcat(myAbsoluteURL, &myGivenURL[1]); |
} else if ((myGivenURL[0] == '.') && (myGivenURL[1] == '.') && (myGivenURL[2] == kWM_URLSeparator)) { |
////////// |
// |
// (2) myGivenURL is a file in a folder above the folder myMovieFolderURL |
// |
// we assume that myGivenURL begins with one or more consecutive occurrences of |
// the string "../" and that the remainder of myGivenURL is a partial URL path |
// with no further "./" or "../" constructs |
// |
////////// |
myIndex = 0; |
while ((myGivenURL[myIndex] == '.') && (myGivenURL[myIndex + 1] == '.') && (myGivenURL[myIndex + 2] == kWM_URLSeparator)) { |
// truncate myMovieFolderURL at the rightmost path separator |
myCount = strlen(myMovieFolderURL) - 1; |
while (myMovieFolderURL[myCount] != kWM_URLSeparator) |
myCount--; |
myMovieFolderURL[myCount] = '\0'; |
myIndex += 3; |
} |
// concatenate the paths for an absolute URL |
strcat(myAbsoluteURL, myMovieFolderURL); |
strcat(myAbsoluteURL, &myGivenURL[myIndex - 1]); |
} else { |
////////// |
// |
// (3) myGivenURL is a file in the folder myMovieFolderURL |
// |
////////// |
// concatenate the paths for an absolute URL |
strcat(myAbsoluteURL, myMovieFolderURL); |
strcat(myAbsoluteURL, "/"); |
strcat(myAbsoluteURL, myGivenURL); |
} |
////////// |
// |
// return the absolute URL to the caller |
// |
////////// |
mySize = (Size)strlen(myAbsoluteURL); |
SetHandleSize(theURLHandle, mySize); |
if (theURLHandle != NULL) |
BlockMove(myAbsoluteURL, *theURLHandle, mySize); |
bail: |
// dispose of any storage we allocated |
if (myMovieFilePath != NULL) |
free(myMovieFilePath); |
if (myMovieFolderURL != NULL) |
free(myMovieFolderURL); |
if (myGivenURL != NULL) |
free(myGivenURL); |
} |
////////// |
// |
// WatchMe_GetLaunchVolumeName |
// Return the name of the volume from which this application was launched, |
// in a form that can be embedded in a full pathname. |
// |
// On Macintosh, this is just the volume's name; on Windows, this is the |
// drive letter and colon (and NOT the volume's name). |
// |
// The caller is responsible for disposing of the pointer returned by this function (by calling free). |
// |
////////// |
char *WatchMe_GetLaunchVolumeName (void) |
{ |
char *myVolName = NULL; |
#if TARGET_OS_MAC |
ProcessSerialNumber myPSN; |
OSErr myErr = noErr; |
#endif |
myVolName = malloc(MAX_PATH); |
if (myVolName == NULL) |
goto bail; |
myVolName[0] = '\0'; |
////////// |
// |
// on Windows, we can use GetCurrentDirectory to get the name of the current directory |
// |
////////// |
#if TARGET_OS_WIN32 |
GetCurrentDirectory(MAX_PATH, myVolName); |
#if TESTING_ON_NONCD |
myVolName[0] = 'E'; // just testing on my local machine, which uses "E" for the CD-ROM |
#else |
myVolName[0] = toupper(myVolName[0]); |
#endif |
// add the ":" that terminates drive names |
myVolName[1] = ':'; |
myVolName[2] = '\0'; |
#endif // TARGET_OS_WIN32 |
////////// |
// |
// on Macintosh, we'll use the Process Manager |
// |
////////// |
#if TARGET_OS_MAC |
myErr = GetCurrentProcess(&myPSN); |
if (myErr == noErr) { |
ProcessInfoRec myInfo; |
FSSpec myFSSpec; |
int myPos = 0; |
myInfo.processInfoLength = sizeof(ProcessInfoRec); |
myInfo.processName = NULL; |
myInfo.processAppSpec = &myFSSpec; |
myErr = GetProcessInformation(&myPSN, &myInfo); |
if (myErr == noErr) { |
// get the full pathname of the application file |
myVolName = WatchMe_FSSpecToFullPath(myInfo.processAppSpec); |
// truncate before the first path separator |
myPos = strcspn(myVolName, ":"); |
myVolName[myPos] = '\0'; |
} |
} |
#if TESTING_ON_NONCD |
myVolName[0] = '\0'; |
strcat(myVolName, "QT3SDK"); |
#endif |
#endif // TARGET_OS_MAC |
bail: |
return(myVolName); |
} |
////////// |
// |
// WatchMe_FSSpecToFullPath |
// Convert an FSSpec into a full native path name. |
// |
// The caller is responsible for disposing of the pointer returned by this function (by calling free). |
// |
////////// |
static char *WatchMe_FSSpecToFullPath (const FSSpec *theFSSpec) |
{ |
char *myPathName = NULL; |
#if TARGET_OS_MAC |
Handle myHandle = NULL; |
short myLength; |
#endif |
if (theFSSpec == NULL) |
goto bail; |
myPathName = malloc(MAX_PATH); |
if (myPathName == NULL) |
goto bail; |
#if TARGET_OS_WIN32 |
// on Windows, this is easy (thanks to those hardworking QuickTime engineers) |
FSSpecToNativePathName(theFSSpec, myPathName, MAX_PATH, kFullNativePath); |
#elif TARGET_OS_MAC |
// on Macintosh, this is easy (thanks to that hardworking Jim Luther) |
WatchMe_FSpGetFullPath(theFSSpec, &myLength, &myHandle); |
BlockMove(*myHandle, myPathName, myLength); |
myPathName[myLength] = '\0'; |
#endif |
bail: |
return(myPathName); |
} |
////////// |
// |
// WatchMe_FullPathToURL |
// Convert a full native pathname into an absolute local URL. |
// |
// The caller is responsible for disposing of the pointer returned by this function (by calling free). |
// |
////////// |
static char *WatchMe_FullPathToURL (char *thePath) |
{ |
char *myURL = NULL; |
UInt16 myIndex; |
if (thePath == NULL) |
goto bail; |
myURL = malloc(MAX_PATH); |
if (myURL == NULL) |
goto bail; |
////////// |
// |
// convert all native path separators into the URL path separator |
// |
////////// |
for (myIndex = 0; myIndex < strlen(thePath); myIndex++) |
if (thePath[myIndex] == kWM_PathSeparator) |
thePath[myIndex] = kWM_URLSeparator; |
////////// |
// |
// convert any special characters in the URL path into their encoded versions; |
// in theory, the URLs we are passed should already be encoded, but we'll make |
// sure before passing the URL to the movie controller |
// |
////////// |
thePath = WatchMe_EncodeURL(thePath); |
////////// |
// |
// prepend the appropriate URL head |
// |
////////// |
myURL[0] = '\0'; |
strcat(myURL, "file:///"); |
////////// |
// |
// append the converted path name to the URL |
// |
////////// |
strcat(myURL, thePath); |
bail: |
return(myURL); |
} |
////////// |
// |
// WatchMe_EncodeURL |
// Convert any special characters in the specified URL path into their encoded versions. |
// |
// Currently, only the space character ' ' is treated specially. |
// |
// Note that this encoding might cause the size of the string to increase; in that case, |
// we'll allocate some new storage and free theURL before returning. |
// |
// The caller is responsible for disposing of the pointer returned by this function (by calling free). |
// |
////////// |
static char *WatchMe_EncodeURL (char *theURL) |
{ |
char *myEncodedURL = NULL; |
char *mySpecialChar = NULL; |
UInt16 myPos, myIndex; |
if (theURL == NULL) |
goto bail; |
// determine whether we actually need to do any work |
mySpecialChar = strchr(theURL, ' '); |
if (mySpecialChar == NULL) { |
myEncodedURL = theURL; // return the string we were passed |
goto bail; |
} |
// theURL contains one or more special characters that need to be encoded; |
// allocate a new string into which we can write the encoded URL |
myEncodedURL = malloc(MAX_PATH); |
if (myEncodedURL == NULL) |
goto bail; |
myPos = 0; |
for (myIndex = 0; myIndex < strlen(theURL); myIndex++) { |
if (theURL[myIndex] == ' ') { |
char myChar; |
myEncodedURL[myPos + 0] = '%'; |
myChar = theURL[myIndex] >> 4; |
myEncodedURL[myPos + 1] = myChar + ((myChar <= 9) ? '0' : ('A' - 10)); |
myChar = theURL[myIndex] & 0xF; |
myEncodedURL[myPos + 2] = myChar + ((myChar <= 9) ? '0' : ('A' - 10)); |
myPos += 3; |
} else { |
myEncodedURL[myPos] = theURL[myIndex]; |
myPos++; |
} |
} |
myEncodedURL[myPos] = '\0'; |
free(theURL); |
bail: |
return(myEncodedURL); |
} |
////////// |
// |
// WatchMe_IsAbsoluteURL |
// Determine whether the specified URL is absolute. |
// |
////////// |
static Boolean WatchMe_IsAbsoluteURL (char *theURL) |
{ |
return(theURL[0] != '.'); |
} |
////////// |
// |
// WatchMe_FSpGetFullPath |
// Get a full path name from an FSSpec. |
// |
// This is straight out of MoreFiles 1.4 by Jim Luther; the only thing I did |
// was to change the name. |
// |
// NOTE: This function is MACINTOSH ONLY. |
// |
////////// |
static OSErr WatchMe_FSpGetFullPath (const FSSpec *spec, short *fullPathLength, Handle *fullPath) |
{ |
OSErr result; |
FSSpec tempSpec; |
CInfoPBRec pb; |
*fullPathLength = 0; |
*fullPath = NULL; |
/* Make a copy of the input FSSpec that can be modified */ |
BlockMoveData(spec, &tempSpec, sizeof(FSSpec)); |
if ( tempSpec.parID == fsRtParID ) |
{ |
/* The object is a volume */ |
/* Add a colon to make it a full pathname */ |
++tempSpec.name[0]; |
tempSpec.name[tempSpec.name[0]] = ':'; |
/* We're done */ |
result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]); |
} |
else |
{ |
/* The object isn't a volume */ |
/* Is the object a file or a directory? */ |
pb.dirInfo.ioNamePtr = tempSpec.name; |
pb.dirInfo.ioVRefNum = tempSpec.vRefNum; |
pb.dirInfo.ioDrDirID = tempSpec.parID; |
pb.dirInfo.ioFDirIndex = 0; |
result = PBGetCatInfoSync(&pb); |
if ( result == noErr ) |
{ |
/* if the object is a directory, append a colon so full pathname ends with colon */ |
if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 ) |
{ |
++tempSpec.name[0]; |
tempSpec.name[tempSpec.name[0]] = ':'; |
} |
/* Put the object name in first */ |
result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]); |
if ( result == noErr ) |
{ |
/* Get the ancestor directory names */ |
pb.dirInfo.ioNamePtr = tempSpec.name; |
pb.dirInfo.ioVRefNum = tempSpec.vRefNum; |
pb.dirInfo.ioDrParID = tempSpec.parID; |
do /* loop until we have an error or find the root directory */ |
{ |
pb.dirInfo.ioFDirIndex = -1; |
pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID; |
result = PBGetCatInfoSync(&pb); |
if ( result == noErr ) |
{ |
/* Append colon to directory name */ |
++tempSpec.name[0]; |
tempSpec.name[tempSpec.name[0]] = ':'; |
/* Add directory name to beginning of fullPath */ |
(void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1], tempSpec.name[0]); |
result = MemError(); |
} |
} while ( (result == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) ); |
} |
} |
} |
if ( result == noErr ) |
{ |
/* Return the length */ |
*fullPathLength = GetHandleSize(*fullPath); |
} |
else |
{ |
/* Dispose of the handle and return NULL and zero length */ |
if ( *fullPath != NULL ) |
{ |
DisposeHandle(*fullPath); |
} |
*fullPath = NULL; |
*fullPathLength = 0; |
} |
return ( result ); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-02-25