tclMacUtil.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:12k
- /*
- * tclMacUtil.c --
- *
- * This contains utility functions used to help with
- * implementing Macintosh specific portions of the Tcl port.
- *
- * Copyright (c) 1993-1994 Lockheed Missle & Space Company, AI Center
- * Copyright (c) 1995-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * RCS: @(#) $Id: tclMacUtil.c,v 1.7 2003/03/03 20:22:44 das Exp $
- */
- #include "tcl.h"
- #include "tclInt.h"
- #include "tclMacInt.h"
- #include "tclMath.h"
- #include "tclMacPort.h"
- #include <Aliases.h>
- #include <Errors.h>
- #include <Files.h>
- #include <Folders.h>
- #include <FSpCompat.h>
- #include <Strings.h>
- #include <TextUtils.h>
- #include <MoreFilesExtras.h>
- /*
- * The following two Includes are from the More Files package.
- */
- #include <FileCopy.h>
- #include <MoreFiles.h>
- /*
- *----------------------------------------------------------------------
- *
- * hypotd --
- *
- * The standard math function hypot is not supported by Think C.
- * It is included here so everything works. It is supported by
- * CodeWarrior Pro 1, but the 68K version does not support doubles.
- * So we hack it in.
- *
- * Results:
- * Result of computation.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- #if defined(THINK_C)
- double hypotd(double x, double y);
- double
- hypotd(
- double x, /* X value */
- double y) /* Y value */
- {
- double sum;
- sum = x*x + y*y;
- return sqrt(sum);
- }
- #endif
- /*
- *----------------------------------------------------------------------
- *
- * FSpGetDefaultDir --
- *
- * This function gets the current default directory.
- *
- * Results:
- * The provided FSSpec is changed to point to the "default"
- * directory. The function returns what ever errors
- * FSMakeFSSpecCompat may encounter.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- int
- FSpGetDefaultDir(
- FSSpecPtr dirSpec) /* On return the default directory. */
- {
- OSErr err;
- short vRefNum = 0;
- long int dirID = 0;
- err = HGetVol(NULL, &vRefNum, &dirID);
-
- if (err == noErr) {
- err = FSMakeFSSpecCompat(vRefNum, dirID, (ConstStr255Param) NULL,
- dirSpec);
- }
-
- return err;
- }
- /*
- *----------------------------------------------------------------------
- *
- * FSpSetDefaultDir --
- *
- * This function sets the default directory to the directory
- * pointed to by the provided FSSpec.
- *
- * Results:
- * The function returns what ever errors HSetVol may encounter.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- int
- FSpSetDefaultDir(
- FSSpecPtr dirSpec) /* The new default directory. */
- {
- OSErr err;
- /*
- * The following special case is needed to work around a bug
- * in the Macintosh OS. (Acutally PC Exchange.)
- */
-
- if (dirSpec->parID == fsRtParID) {
- err = HSetVol(NULL, dirSpec->vRefNum, fsRtDirID);
- } else {
- err = HSetVol(dirSpec->name, dirSpec->vRefNum, dirSpec->parID);
- }
-
- return err;
- }
- /*
- *----------------------------------------------------------------------
- *
- * FSpFindFolder --
- *
- * This function is a version of the FindFolder function that
- * returns the result as a FSSpec rather than a vRefNum and dirID.
- *
- * Results:
- * Results will be simaler to that of the FindFolder function.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- OSErr
- FSpFindFolder(
- short vRefNum, /* Volume reference number. */
- OSType folderType, /* Folder type taken by FindFolder. */
- Boolean createFolder, /* Should we create it if non-existant. */
- FSSpec *spec) /* Pointer to resulting directory. */
- {
- short foundVRefNum;
- long foundDirID;
- OSErr err;
- err = FindFolder(vRefNum, folderType, createFolder,
- &foundVRefNum, &foundDirID);
- if (err != noErr) {
- return err;
- }
-
- err = FSMakeFSSpecCompat(foundVRefNum, foundDirID, "p", spec);
- return err;
- }
- static int
- FSpLocationFromPathAlias _ANSI_ARGS_((int length, CONST char *path,
- FSSpecPtr fileSpecPtr, Boolean resolveLink));
- /*
- *----------------------------------------------------------------------
- *
- * FSpLocationFromPath --
- *
- * This function obtains an FSSpec for a given macintosh path.
- * Unlike the More Files function FSpLocationFromFullPath, this
- * function will also accept partial paths and resolve any aliases
- * along the path.
- *
- * Results:
- * OSErr code.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- int
- FSpLocationFromPath(
- int length, /* Length of path. */
- CONST char *path, /* The path to convert. */
- FSSpecPtr fileSpecPtr) /* On return the spec for the path. */
- {
- return FSpLocationFromPathAlias(length, path, fileSpecPtr, TRUE);
- }
- /*
- *----------------------------------------------------------------------
- *
- * FSpLLocationFromPath --
- *
- * This function obtains an FSSpec for a given macintosh path.
- * Unlike the More Files function FSpLocationFromFullPath, this
- * function will also accept partial paths and resolve any aliases
- * along the path expect for the last path component.
- *
- * Results:
- * OSErr code.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- int
- FSpLLocationFromPath(
- int length, /* Length of path. */
- CONST char *path, /* The path to convert. */
- FSSpecPtr fileSpecPtr) /* On return the spec for the path. */
- {
- return FSpLocationFromPathAlias(length, path, fileSpecPtr, FALSE);
- }
- static int
- FSpLocationFromPathAlias(
- int length, /* Length of path. */
- CONST char *path, /* The path to convert. */
- FSSpecPtr fileSpecPtr, /* On return the spec for the path. */
- Boolean resolveLink) /* Resolve the last path component? */
- {
- Str255 fileName;
- OSErr err;
- short vRefNum;
- long dirID;
- int pos, cur;
- Boolean isDirectory;
- Boolean wasAlias=FALSE;
- FSSpec lastFileSpec;
- /*
- * Check to see if this is a full path. If partial
- * we assume that path starts with the current working
- * directory. (Ie. volume & dir = 0)
- */
- vRefNum = 0;
- dirID = 0;
- cur = 0;
- if (length == 0) {
- return fnfErr;
- }
- if (path[cur] == ':') {
- cur++;
- if (cur >= length) {
- /*
- * If path = ":", just return current directory.
- */
- FSMakeFSSpecCompat(0, 0, NULL, fileSpecPtr);
- return noErr;
- }
- } else {
- while (path[cur] != ':' && cur < length) {
- cur++;
- }
- if (cur > 255) {
- return bdNamErr;
- }
- if (cur < length) {
- /*
- * This is a full path
- */
- cur++;
- strncpy((char *) fileName + 1, path, cur);
- fileName[0] = cur;
- err = FSMakeFSSpecCompat(0, 0, fileName, fileSpecPtr);
- if (err != noErr) return err;
- FSpGetDirectoryID(fileSpecPtr, &dirID, &isDirectory);
- vRefNum = fileSpecPtr->vRefNum;
- } else {
- cur = 0;
- }
- }
-
- isDirectory = 1;
- while (cur < length) {
- if (!isDirectory) {
- return dirNFErr;
- }
- pos = cur;
- while (path[pos] != ':' && pos < length) {
- pos++;
- }
- if (pos == cur) {
- /* Move up one dir */
- /* cur++; */
- strcpy((char *) fileName + 1, "::");
- fileName[0] = 2;
- } else if (pos - cur > 255) {
- return bdNamErr;
- } else {
- strncpy((char *) fileName + 1, &path[cur], pos - cur);
- fileName[0] = pos - cur;
- }
- err = FSMakeFSSpecCompat(vRefNum, dirID, fileName, fileSpecPtr);
- if (err != noErr) return err;
- lastFileSpec=*fileSpecPtr;
- err = ResolveAliasFile(fileSpecPtr, true, &isDirectory, &wasAlias);
- if (err != noErr) {
- /* ignore alias resolve errors on last path component */
- if (pos < length) return err;
- else *fileSpecPtr=lastFileSpec;
- }
- FSpGetDirectoryID(fileSpecPtr, &dirID, &isDirectory);
- vRefNum = fileSpecPtr->vRefNum;
- cur = pos;
- if (path[cur] == ':') {
- cur++;
- }
- }
-
- if(!resolveLink && wasAlias)
- *fileSpecPtr=lastFileSpec;
-
- return noErr;
- }
- /*
- *----------------------------------------------------------------------
- *
- * FSpPathFromLocation --
- *
- * This function obtains a full path name for a given macintosh
- * FSSpec. Unlike the More Files function FSpGetFullPath, this
- * function will return a C string in the Handle. It also will
- * create paths for FSSpec that do not yet exist.
- *
- * Results:
- * OSErr code.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- OSErr
- FSpPathFromLocation(
- FSSpec *spec, /* The location we want a path for. */
- int *length, /* Length of the resulting path. */
- Handle *fullPath) /* Handle to path. */
- {
- OSErr err;
- FSSpec tempSpec;
- CInfoPBRec pb;
-
- *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. Allocate a handle for it and we are done.
- */
- tempSpec.name[0] += 2;
- tempSpec.name[tempSpec.name[0] - 1] = ':';
- tempSpec.name[tempSpec.name[0]] = ' ';
-
- err = 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;
- err = PBGetCatInfoSync(&pb);
- if ((err == noErr) || (err == fnfErr)) {
- /*
- * If the file doesn't currently exist we start over. If the
- * directory exists everything will work just fine. Otherwise we
- * will just fail later. If the object is a directory, append a
- * colon so full pathname ends with colon, but only if the name is
- * not empty. NavServices returns FSSpec's with the parent ID set,
- * but the name empty...
- */
- if (err == fnfErr) {
- BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
- } else if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 ) {
- if (tempSpec.name[0] > 0) {
- tempSpec.name[0] += 1;
- tempSpec.name[tempSpec.name[0]] = ':';
- }
- }
-
- /*
- * Create a new Handle for the object - make it a C string.
- */
- tempSpec.name[0] += 1;
- tempSpec.name[tempSpec.name[0]] = ' ';
- err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
- if (err == noErr) {
- /*
- * Get the ancestor directory names - loop until we have an
- * error or find the root directory.
- */
- pb.dirInfo.ioNamePtr = tempSpec.name;
- pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
- pb.dirInfo.ioDrParID = tempSpec.parID;
- do {
- pb.dirInfo.ioFDirIndex = -1;
- pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
- err = PBGetCatInfoSync(&pb);
- if (err == noErr) {
- /*
- * Append colon to directory name and add
- * directory name to beginning of fullPath.
- */
- ++tempSpec.name[0];
- tempSpec.name[tempSpec.name[0]] = ':';
-
- (void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1],
- tempSpec.name[0]);
- err = MemError();
- }
- } while ( (err == noErr) &&
- (pb.dirInfo.ioDrDirID != fsRtDirID) );
- }
- }
- }
-
- /*
- * On error Dispose the handle, set it to NULL & return the err.
- * Otherwise, set the length & return.
- */
- if (err == noErr) {
- *length = GetHandleSize(*fullPath) - 1;
- } else {
- if ( *fullPath != NULL ) {
- DisposeHandle(*fullPath);
- }
- *fullPath = NULL;
- *length = 0;
- }
- return err;
- }
- /*
- *----------------------------------------------------------------------
- *
- * GetGlobalMouseTcl --
- *
- * This procedure obtains the current mouse position in global
- * coordinates.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- void
- GetGlobalMouseTcl(
- Point *mouse) /* Mouse position. */
- {
- EventRecord event;
-
- OSEventAvail(0, &event);
- *mouse = event.where;
- }
- pascal OSErr FSpGetDirectoryIDTcl (CONST FSSpec * spec,
- long * theDirID, Boolean * isDirectory)
- {
- return(FSpGetDirectoryID(spec, theDirID, isDirectory));
- }
- pascal short FSpOpenResFileCompatTcl (CONST FSSpec * spec, SignedByte permission)
- {
- return(FSpOpenResFileCompat(spec,permission));
- }
- pascal void FSpCreateResFileCompatTcl (
- CONST FSSpec * spec, OSType creator,
- OSType fileType, ScriptCode scriptTag)
- {
- FSpCreateResFileCompat (spec,creator,fileType,scriptTag);
- }