os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/mac/tclMacUtil.c
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/mac/tclMacUtil.c	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,514 @@
     1.4 +/* 
     1.5 + * tclMacUtil.c --
     1.6 + *
     1.7 + *  This contains utility functions used to help with
     1.8 + *  implementing Macintosh specific portions of the Tcl port.
     1.9 + *
    1.10 + * Copyright (c) 1993-1994 Lockheed Missle & Space Company, AI Center
    1.11 + * Copyright (c) 1995-1997 Sun Microsystems, Inc.
    1.12 + *
    1.13 + * See the file "license.terms" for information on usage and redistribution
    1.14 + * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    1.15 + *
    1.16 + * RCS: @(#) $Id: tclMacUtil.c,v 1.7 2003/03/03 20:22:44 das Exp $
    1.17 + */
    1.18 +
    1.19 +#include "tcl.h"
    1.20 +#include "tclInt.h"
    1.21 +#include "tclMacInt.h"
    1.22 +#include "tclMath.h"
    1.23 +#include "tclMacPort.h"
    1.24 +
    1.25 +#include <Aliases.h>
    1.26 +#include <Errors.h>
    1.27 +#include <Files.h>
    1.28 +#include <Folders.h>
    1.29 +#include <FSpCompat.h>
    1.30 +#include <Strings.h>
    1.31 +#include <TextUtils.h>
    1.32 +#include <MoreFilesExtras.h>
    1.33 +
    1.34 +/* 
    1.35 + * The following two Includes are from the More Files package.
    1.36 + */
    1.37 +#include <FileCopy.h>
    1.38 +#include <MoreFiles.h>
    1.39 +
    1.40 +/*
    1.41 + *----------------------------------------------------------------------
    1.42 + *
    1.43 + * hypotd --
    1.44 + *
    1.45 + *	The standard math function hypot is not supported by Think C.
    1.46 + *	It is included here so everything works. It is supported by
    1.47 + *	CodeWarrior Pro 1, but the 68K version does not support doubles.
    1.48 + *	So we hack it in.
    1.49 + *
    1.50 + * Results:
    1.51 + *	Result of computation.
    1.52 + *
    1.53 + * Side effects:
    1.54 + *	None.
    1.55 + *
    1.56 + *----------------------------------------------------------------------
    1.57 + */
    1.58 + 
    1.59 +#if defined(THINK_C)
    1.60 +double hypotd(double x, double y);
    1.61 +
    1.62 +double
    1.63 +hypotd(
    1.64 +    double x,		/* X value */
    1.65 +    double y)		/* Y value */
    1.66 +{
    1.67 +    double sum;
    1.68 +
    1.69 +    sum = x*x + y*y;
    1.70 +    return sqrt(sum);
    1.71 +}
    1.72 +#endif
    1.73 +
    1.74 +/*
    1.75 + *----------------------------------------------------------------------
    1.76 + *
    1.77 + * FSpGetDefaultDir --
    1.78 + *
    1.79 + *	This function gets the current default directory.
    1.80 + *
    1.81 + * Results:
    1.82 + *	The provided FSSpec is changed to point to the "default"
    1.83 + *	directory.  The function returns what ever errors
    1.84 + *	FSMakeFSSpecCompat may encounter.
    1.85 + *
    1.86 + * Side effects:
    1.87 + *	None.
    1.88 + *
    1.89 + *----------------------------------------------------------------------
    1.90 + */
    1.91 +
    1.92 +int
    1.93 +FSpGetDefaultDir(
    1.94 +	FSSpecPtr dirSpec)	/* On return the default directory. */
    1.95 +{
    1.96 +    OSErr err;
    1.97 +    short vRefNum = 0;
    1.98 +    long int dirID = 0;
    1.99 +
   1.100 +    err = HGetVol(NULL, &vRefNum, &dirID);
   1.101 +	
   1.102 +    if (err == noErr) {
   1.103 +	err = FSMakeFSSpecCompat(vRefNum, dirID, (ConstStr255Param) NULL,
   1.104 +		dirSpec);
   1.105 +    }
   1.106 +	
   1.107 +    return err;
   1.108 +}
   1.109 +
   1.110 +/*
   1.111 + *----------------------------------------------------------------------
   1.112 + *
   1.113 + * FSpSetDefaultDir --
   1.114 + *
   1.115 + *	This function sets the default directory to the directory
   1.116 + *	pointed to by the provided FSSpec.
   1.117 + *
   1.118 + * Results:
   1.119 + *	The function returns what ever errors HSetVol may encounter.
   1.120 + *
   1.121 + * Side effects:
   1.122 + *	None.
   1.123 + *
   1.124 + *----------------------------------------------------------------------
   1.125 + */
   1.126 +
   1.127 +int
   1.128 +FSpSetDefaultDir(
   1.129 +	FSSpecPtr dirSpec)	/* The new default directory. */
   1.130 +{
   1.131 +    OSErr err;
   1.132 +
   1.133 +    /*
   1.134 +     * The following special case is needed to work around a bug
   1.135 +     * in the Macintosh OS.  (Acutally PC Exchange.)
   1.136 +     */
   1.137 +    
   1.138 +    if (dirSpec->parID == fsRtParID) {
   1.139 +	err = HSetVol(NULL, dirSpec->vRefNum, fsRtDirID);
   1.140 +    } else {
   1.141 +	err = HSetVol(dirSpec->name, dirSpec->vRefNum, dirSpec->parID);
   1.142 +    }
   1.143 +    
   1.144 +    return err;
   1.145 +}
   1.146 +
   1.147 +/*
   1.148 + *----------------------------------------------------------------------
   1.149 + *
   1.150 + * FSpFindFolder --
   1.151 + *
   1.152 + *	This function is a version of the FindFolder function that 
   1.153 + *	returns the result as a FSSpec rather than a vRefNum and dirID.
   1.154 + *
   1.155 + * Results:
   1.156 + *	Results will be simaler to that of the FindFolder function.
   1.157 + *
   1.158 + * Side effects:
   1.159 + *	None.
   1.160 + *
   1.161 + *----------------------------------------------------------------------
   1.162 + */
   1.163 +
   1.164 +OSErr
   1.165 +FSpFindFolder(
   1.166 +    short vRefNum,		/* Volume reference number. */
   1.167 +    OSType folderType,		/* Folder type taken by FindFolder. */
   1.168 +    Boolean createFolder,	/* Should we create it if non-existant. */
   1.169 +    FSSpec *spec)		/* Pointer to resulting directory. */
   1.170 +{
   1.171 +    short foundVRefNum;
   1.172 +    long foundDirID;
   1.173 +    OSErr err;
   1.174 +
   1.175 +    err = FindFolder(vRefNum, folderType, createFolder,
   1.176 +	    &foundVRefNum, &foundDirID);
   1.177 +    if (err != noErr) {
   1.178 +	return err;
   1.179 +    }
   1.180 +		
   1.181 +    err = FSMakeFSSpecCompat(foundVRefNum, foundDirID, "\p", spec);
   1.182 +    return err;
   1.183 +}
   1.184 +
   1.185 +static int
   1.186 +FSpLocationFromPathAlias _ANSI_ARGS_((int length, CONST char *path,
   1.187 +	FSSpecPtr fileSpecPtr, Boolean resolveLink));
   1.188 +
   1.189 +/*
   1.190 + *----------------------------------------------------------------------
   1.191 + *
   1.192 + * FSpLocationFromPath --
   1.193 + *
   1.194 + *	This function obtains an FSSpec for a given macintosh path.
   1.195 + *	Unlike the More Files function FSpLocationFromFullPath, this
   1.196 + *	function will also accept partial paths and resolve any aliases
   1.197 + *	along the path.  
   1.198 + *
   1.199 + * Results:
   1.200 + *	OSErr code.
   1.201 + *
   1.202 + * Side effects:
   1.203 + *	None.
   1.204 + *
   1.205 + *----------------------------------------------------------------------
   1.206 + */
   1.207 +
   1.208 +int
   1.209 +FSpLocationFromPath(
   1.210 +    int length,			/* Length of path. */
   1.211 +    CONST char *path,		/* The path to convert. */
   1.212 +    FSSpecPtr fileSpecPtr)	/* On return the spec for the path. */
   1.213 +{
   1.214 +	return FSpLocationFromPathAlias(length, path, fileSpecPtr, TRUE);
   1.215 +}
   1.216 +
   1.217 +/*
   1.218 + *----------------------------------------------------------------------
   1.219 + *
   1.220 + * FSpLLocationFromPath --
   1.221 + *
   1.222 + *	This function obtains an FSSpec for a given macintosh path.
   1.223 + *	Unlike the More Files function FSpLocationFromFullPath, this
   1.224 + *	function will also accept partial paths and resolve any aliases
   1.225 + *	along the path expect for the last path component.
   1.226 + *
   1.227 + * Results:
   1.228 + *	OSErr code.
   1.229 + *
   1.230 + * Side effects:
   1.231 + *	None.
   1.232 + *
   1.233 + *----------------------------------------------------------------------
   1.234 + */
   1.235 +
   1.236 +int
   1.237 +FSpLLocationFromPath(
   1.238 +    int length,			/* Length of path. */
   1.239 +    CONST char *path,		/* The path to convert. */
   1.240 +    FSSpecPtr fileSpecPtr)	/* On return the spec for the path. */
   1.241 +{
   1.242 +	return FSpLocationFromPathAlias(length, path, fileSpecPtr, FALSE);
   1.243 +}
   1.244 +
   1.245 +static int
   1.246 +FSpLocationFromPathAlias(
   1.247 +    int length,			/* Length of path. */
   1.248 +    CONST char *path,		/* The path to convert. */
   1.249 +    FSSpecPtr fileSpecPtr,	/* On return the spec for the path. */
   1.250 +    Boolean resolveLink)	/* Resolve the last path component? */
   1.251 +{
   1.252 +    Str255 fileName;
   1.253 +    OSErr err;
   1.254 +    short vRefNum;
   1.255 +    long dirID;
   1.256 +    int pos, cur;
   1.257 +    Boolean isDirectory;
   1.258 +    Boolean wasAlias=FALSE;
   1.259 +    FSSpec lastFileSpec;
   1.260 +
   1.261 +    /*
   1.262 +     * Check to see if this is a full path.  If partial
   1.263 +     * we assume that path starts with the current working
   1.264 +     * directory.  (Ie. volume & dir = 0)
   1.265 +     */
   1.266 +    vRefNum = 0;
   1.267 +    dirID = 0;
   1.268 +    cur = 0;
   1.269 +    if (length == 0) {
   1.270 +        return fnfErr;
   1.271 +    }
   1.272 +    if (path[cur] == ':') {
   1.273 +	cur++;
   1.274 +	if (cur >= length) {
   1.275 +	    /*
   1.276 +	     * If path = ":", just return current directory.
   1.277 +	     */
   1.278 +	    FSMakeFSSpecCompat(0, 0, NULL, fileSpecPtr);
   1.279 +	    return noErr;
   1.280 +	}
   1.281 +    } else {
   1.282 +	while (path[cur] != ':' && cur < length) {
   1.283 +	    cur++;
   1.284 +	}
   1.285 +	if (cur > 255) {
   1.286 +	    return bdNamErr;
   1.287 +	}
   1.288 +	if (cur < length) {
   1.289 +	    /*
   1.290 +	     * This is a full path
   1.291 +	     */
   1.292 +	    cur++;
   1.293 +	    strncpy((char *) fileName + 1, path, cur);
   1.294 +	    fileName[0] = cur;
   1.295 +	    err = FSMakeFSSpecCompat(0, 0, fileName, fileSpecPtr);
   1.296 +	    if (err != noErr) return err;
   1.297 +	    FSpGetDirectoryID(fileSpecPtr, &dirID, &isDirectory);
   1.298 +	    vRefNum = fileSpecPtr->vRefNum;
   1.299 +	} else {
   1.300 +	    cur = 0;
   1.301 +	}
   1.302 +    }
   1.303 +    
   1.304 +    isDirectory = 1;
   1.305 +    while (cur < length) {
   1.306 +	if (!isDirectory) {
   1.307 +	    return dirNFErr;
   1.308 +	}
   1.309 +	pos = cur;
   1.310 +	while (path[pos] != ':' && pos < length) {
   1.311 +	    pos++;
   1.312 +	}
   1.313 +	if (pos == cur) {
   1.314 +	    /* Move up one dir */
   1.315 +	    /* cur++; */
   1.316 +	    strcpy((char *) fileName + 1, "::");
   1.317 +	    fileName[0] = 2;
   1.318 +	} else if (pos - cur > 255) {
   1.319 +	    return bdNamErr;
   1.320 +	} else {
   1.321 +	    strncpy((char *) fileName + 1, &path[cur], pos - cur);
   1.322 +	    fileName[0] = pos - cur;
   1.323 +	}
   1.324 +	err = FSMakeFSSpecCompat(vRefNum, dirID, fileName, fileSpecPtr);
   1.325 +	if (err != noErr) return err;
   1.326 +	lastFileSpec=*fileSpecPtr;
   1.327 +	err = ResolveAliasFile(fileSpecPtr, true, &isDirectory, &wasAlias);
   1.328 +	if (err != noErr) {
   1.329 +	    /* ignore alias resolve errors on last path component */
   1.330 +	    if (pos < length) return err;
   1.331 +	    else *fileSpecPtr=lastFileSpec;
   1.332 +	}
   1.333 +	FSpGetDirectoryID(fileSpecPtr, &dirID, &isDirectory);
   1.334 +	vRefNum = fileSpecPtr->vRefNum;
   1.335 +	cur = pos;
   1.336 +	if (path[cur] == ':') {
   1.337 +	    cur++;
   1.338 +	}
   1.339 +    }
   1.340 +    
   1.341 +    if(!resolveLink && wasAlias)
   1.342 +    	*fileSpecPtr=lastFileSpec;
   1.343 +    
   1.344 +    return noErr;
   1.345 +}
   1.346 +
   1.347 +/*
   1.348 + *----------------------------------------------------------------------
   1.349 + *
   1.350 + * FSpPathFromLocation --
   1.351 + *
   1.352 + *	This function obtains a full path name for a given macintosh
   1.353 + *	FSSpec.  Unlike the More Files function FSpGetFullPath, this
   1.354 + *	function will return a C string in the Handle.  It also will
   1.355 + *	create paths for FSSpec that do not yet exist.
   1.356 + *
   1.357 + * Results:
   1.358 + *	OSErr code.
   1.359 + *
   1.360 + * Side effects:
   1.361 + *	None.
   1.362 + *
   1.363 + *----------------------------------------------------------------------
   1.364 + */
   1.365 +
   1.366 +OSErr
   1.367 +FSpPathFromLocation(
   1.368 +    FSSpec *spec,		/* The location we want a path for. */
   1.369 +    int *length,		/* Length of the resulting path. */
   1.370 +    Handle *fullPath)		/* Handle to path. */
   1.371 +{
   1.372 +    OSErr err;
   1.373 +    FSSpec tempSpec;
   1.374 +    CInfoPBRec pb;
   1.375 +	
   1.376 +    *fullPath = NULL;
   1.377 +	
   1.378 +    /* 
   1.379 +     * Make a copy of the input FSSpec that can be modified.
   1.380 +     */
   1.381 +    BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
   1.382 +	
   1.383 +    if (tempSpec.parID == fsRtParID) {
   1.384 +	/* 
   1.385 +	 * The object is a volume.  Add a colon to make it a full 
   1.386 +	 * pathname.  Allocate a handle for it and we are done.
   1.387 +	 */
   1.388 +	tempSpec.name[0] += 2;
   1.389 +	tempSpec.name[tempSpec.name[0] - 1] = ':';
   1.390 +	tempSpec.name[tempSpec.name[0]] = '\0';
   1.391 +		
   1.392 +	err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
   1.393 +    } else {
   1.394 +	/* 
   1.395 +	 * The object isn't a volume.  Is the object a file or a directory? 
   1.396 +	 */
   1.397 +	pb.dirInfo.ioNamePtr = tempSpec.name;
   1.398 +	pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
   1.399 +	pb.dirInfo.ioDrDirID = tempSpec.parID;
   1.400 +	pb.dirInfo.ioFDirIndex = 0;
   1.401 +	err = PBGetCatInfoSync(&pb);
   1.402 +
   1.403 +	if ((err == noErr) || (err == fnfErr)) {
   1.404 +	    /* 
   1.405 +	     * If the file doesn't currently exist we start over.  If the
   1.406 +	     * directory exists everything will work just fine.  Otherwise we
   1.407 +	     * will just fail later.  If the object is a directory, append a
   1.408 +	     * colon so full pathname ends with colon, but only if the name is
   1.409 +	     * not empty.  NavServices returns FSSpec's with the parent ID set,
   1.410 +	     * but the name empty...
   1.411 +	     */
   1.412 +	    if (err == fnfErr) {
   1.413 +		BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
   1.414 +	    } else if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 ) {
   1.415 +	        if (tempSpec.name[0] > 0) {
   1.416 +		    tempSpec.name[0] += 1;
   1.417 +		    tempSpec.name[tempSpec.name[0]] = ':';
   1.418 +		}
   1.419 +	    }
   1.420 +			
   1.421 +	    /* 
   1.422 +	     * Create a new Handle for the object - make it a C string.
   1.423 +	     */
   1.424 +	    tempSpec.name[0] += 1;
   1.425 +	    tempSpec.name[tempSpec.name[0]] = '\0';
   1.426 +	    err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
   1.427 +	    if (err == noErr) {
   1.428 +		/* 
   1.429 +		 * Get the ancestor directory names - loop until we have an 
   1.430 +		 * error or find the root directory.
   1.431 +		 */
   1.432 +		pb.dirInfo.ioNamePtr = tempSpec.name;
   1.433 +		pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
   1.434 +		pb.dirInfo.ioDrParID = tempSpec.parID;
   1.435 +		do {
   1.436 +		    pb.dirInfo.ioFDirIndex = -1;
   1.437 +		    pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
   1.438 +		    err = PBGetCatInfoSync(&pb);
   1.439 +		    if (err == noErr) {
   1.440 +			/* 
   1.441 +			 * Append colon to directory name and add 
   1.442 +			 * directory name to beginning of fullPath.
   1.443 +			 */
   1.444 +			++tempSpec.name[0];
   1.445 +			tempSpec.name[tempSpec.name[0]] = ':';
   1.446 +						
   1.447 +			(void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1],
   1.448 +				tempSpec.name[0]);
   1.449 +			err = MemError();
   1.450 +		    }
   1.451 +		} while ( (err == noErr) &&
   1.452 +			(pb.dirInfo.ioDrDirID != fsRtDirID) );
   1.453 +	    }
   1.454 +	}
   1.455 +    }
   1.456 +    
   1.457 +    /*
   1.458 +     * On error Dispose the handle, set it to NULL & return the err.
   1.459 +     * Otherwise, set the length & return.
   1.460 +     */
   1.461 +    if (err == noErr) {
   1.462 +	*length = GetHandleSize(*fullPath) - 1;
   1.463 +    } else {
   1.464 +	if ( *fullPath != NULL ) {
   1.465 +	    DisposeHandle(*fullPath);
   1.466 +	}
   1.467 +	*fullPath = NULL;
   1.468 +	*length = 0;
   1.469 +    }
   1.470 +
   1.471 +    return err;
   1.472 +}
   1.473 +
   1.474 +/*
   1.475 + *----------------------------------------------------------------------
   1.476 + *
   1.477 + * GetGlobalMouseTcl --
   1.478 + *
   1.479 + *	This procedure obtains the current mouse position in global
   1.480 + *	coordinates.
   1.481 + *
   1.482 + * Results:
   1.483 + *	None.
   1.484 + *
   1.485 + * Side effects:
   1.486 + *	None.
   1.487 + *
   1.488 + *----------------------------------------------------------------------
   1.489 + */
   1.490 +
   1.491 +void
   1.492 +GetGlobalMouseTcl(
   1.493 +    Point *mouse)		/* Mouse position. */
   1.494 +{
   1.495 +    EventRecord event;
   1.496 +    
   1.497 +    OSEventAvail(0, &event);
   1.498 +    *mouse = event.where;
   1.499 +}
   1.500 +
   1.501 +pascal OSErr	FSpGetDirectoryIDTcl (CONST FSSpec * spec, 
   1.502 +				long * theDirID, Boolean * isDirectory)
   1.503 +{
   1.504 +	return(FSpGetDirectoryID(spec, theDirID, isDirectory));
   1.505 +}
   1.506 +
   1.507 +pascal short	FSpOpenResFileCompatTcl (CONST FSSpec * spec, SignedByte permission)
   1.508 +{
   1.509 +	return(FSpOpenResFileCompat(spec,permission));
   1.510 +}
   1.511 +
   1.512 +pascal void	FSpCreateResFileCompatTcl (
   1.513 +				CONST FSSpec * spec, OSType creator, 
   1.514 +				OSType fileType, ScriptCode scriptTag)
   1.515 +{
   1.516 +	FSpCreateResFileCompat (spec,creator,fileType,scriptTag);
   1.517 +}