os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/mac/tclMacUtil.c
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 +}