tclMacUtil.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:12k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tclMacUtil.c --
  3.  *
  4.  *  This contains utility functions used to help with
  5.  *  implementing Macintosh specific portions of the Tcl port.
  6.  *
  7.  * Copyright (c) 1993-1994 Lockheed Missle & Space Company, AI Center
  8.  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
  9.  *
  10.  * See the file "license.terms" for information on usage and redistribution
  11.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  12.  *
  13.  * RCS: @(#) $Id: tclMacUtil.c,v 1.7 2003/03/03 20:22:44 das Exp $
  14.  */
  15. #include "tcl.h"
  16. #include "tclInt.h"
  17. #include "tclMacInt.h"
  18. #include "tclMath.h"
  19. #include "tclMacPort.h"
  20. #include <Aliases.h>
  21. #include <Errors.h>
  22. #include <Files.h>
  23. #include <Folders.h>
  24. #include <FSpCompat.h>
  25. #include <Strings.h>
  26. #include <TextUtils.h>
  27. #include <MoreFilesExtras.h>
  28. /* 
  29.  * The following two Includes are from the More Files package.
  30.  */
  31. #include <FileCopy.h>
  32. #include <MoreFiles.h>
  33. /*
  34.  *----------------------------------------------------------------------
  35.  *
  36.  * hypotd --
  37.  *
  38.  * The standard math function hypot is not supported by Think C.
  39.  * It is included here so everything works. It is supported by
  40.  * CodeWarrior Pro 1, but the 68K version does not support doubles.
  41.  * So we hack it in.
  42.  *
  43.  * Results:
  44.  * Result of computation.
  45.  *
  46.  * Side effects:
  47.  * None.
  48.  *
  49.  *----------------------------------------------------------------------
  50.  */
  51.  
  52. #if defined(THINK_C)
  53. double hypotd(double x, double y);
  54. double
  55. hypotd(
  56.     double x, /* X value */
  57.     double y) /* Y value */
  58. {
  59.     double sum;
  60.     sum = x*x + y*y;
  61.     return sqrt(sum);
  62. }
  63. #endif
  64. /*
  65.  *----------------------------------------------------------------------
  66.  *
  67.  * FSpGetDefaultDir --
  68.  *
  69.  * This function gets the current default directory.
  70.  *
  71.  * Results:
  72.  * The provided FSSpec is changed to point to the "default"
  73.  * directory.  The function returns what ever errors
  74.  * FSMakeFSSpecCompat may encounter.
  75.  *
  76.  * Side effects:
  77.  * None.
  78.  *
  79.  *----------------------------------------------------------------------
  80.  */
  81. int
  82. FSpGetDefaultDir(
  83. FSSpecPtr dirSpec) /* On return the default directory. */
  84. {
  85.     OSErr err;
  86.     short vRefNum = 0;
  87.     long int dirID = 0;
  88.     err = HGetVol(NULL, &vRefNum, &dirID);
  89.     if (err == noErr) {
  90. err = FSMakeFSSpecCompat(vRefNum, dirID, (ConstStr255Param) NULL,
  91. dirSpec);
  92.     }
  93.     return err;
  94. }
  95. /*
  96.  *----------------------------------------------------------------------
  97.  *
  98.  * FSpSetDefaultDir --
  99.  *
  100.  * This function sets the default directory to the directory
  101.  * pointed to by the provided FSSpec.
  102.  *
  103.  * Results:
  104.  * The function returns what ever errors HSetVol may encounter.
  105.  *
  106.  * Side effects:
  107.  * None.
  108.  *
  109.  *----------------------------------------------------------------------
  110.  */
  111. int
  112. FSpSetDefaultDir(
  113. FSSpecPtr dirSpec) /* The new default directory. */
  114. {
  115.     OSErr err;
  116.     /*
  117.      * The following special case is needed to work around a bug
  118.      * in the Macintosh OS.  (Acutally PC Exchange.)
  119.      */
  120.     
  121.     if (dirSpec->parID == fsRtParID) {
  122. err = HSetVol(NULL, dirSpec->vRefNum, fsRtDirID);
  123.     } else {
  124. err = HSetVol(dirSpec->name, dirSpec->vRefNum, dirSpec->parID);
  125.     }
  126.     
  127.     return err;
  128. }
  129. /*
  130.  *----------------------------------------------------------------------
  131.  *
  132.  * FSpFindFolder --
  133.  *
  134.  * This function is a version of the FindFolder function that 
  135.  * returns the result as a FSSpec rather than a vRefNum and dirID.
  136.  *
  137.  * Results:
  138.  * Results will be simaler to that of the FindFolder function.
  139.  *
  140.  * Side effects:
  141.  * None.
  142.  *
  143.  *----------------------------------------------------------------------
  144.  */
  145. OSErr
  146. FSpFindFolder(
  147.     short vRefNum, /* Volume reference number. */
  148.     OSType folderType, /* Folder type taken by FindFolder. */
  149.     Boolean createFolder, /* Should we create it if non-existant. */
  150.     FSSpec *spec) /* Pointer to resulting directory. */
  151. {
  152.     short foundVRefNum;
  153.     long foundDirID;
  154.     OSErr err;
  155.     err = FindFolder(vRefNum, folderType, createFolder,
  156.     &foundVRefNum, &foundDirID);
  157.     if (err != noErr) {
  158. return err;
  159.     }
  160.     err = FSMakeFSSpecCompat(foundVRefNum, foundDirID, "p", spec);
  161.     return err;
  162. }
  163. static int
  164. FSpLocationFromPathAlias _ANSI_ARGS_((int length, CONST char *path,
  165. FSSpecPtr fileSpecPtr, Boolean resolveLink));
  166. /*
  167.  *----------------------------------------------------------------------
  168.  *
  169.  * FSpLocationFromPath --
  170.  *
  171.  * This function obtains an FSSpec for a given macintosh path.
  172.  * Unlike the More Files function FSpLocationFromFullPath, this
  173.  * function will also accept partial paths and resolve any aliases
  174.  * along the path.  
  175.  *
  176.  * Results:
  177.  * OSErr code.
  178.  *
  179.  * Side effects:
  180.  * None.
  181.  *
  182.  *----------------------------------------------------------------------
  183.  */
  184. int
  185. FSpLocationFromPath(
  186.     int length, /* Length of path. */
  187.     CONST char *path, /* The path to convert. */
  188.     FSSpecPtr fileSpecPtr) /* On return the spec for the path. */
  189. {
  190. return FSpLocationFromPathAlias(length, path, fileSpecPtr, TRUE);
  191. }
  192. /*
  193.  *----------------------------------------------------------------------
  194.  *
  195.  * FSpLLocationFromPath --
  196.  *
  197.  * This function obtains an FSSpec for a given macintosh path.
  198.  * Unlike the More Files function FSpLocationFromFullPath, this
  199.  * function will also accept partial paths and resolve any aliases
  200.  * along the path expect for the last path component.
  201.  *
  202.  * Results:
  203.  * OSErr code.
  204.  *
  205.  * Side effects:
  206.  * None.
  207.  *
  208.  *----------------------------------------------------------------------
  209.  */
  210. int
  211. FSpLLocationFromPath(
  212.     int length, /* Length of path. */
  213.     CONST char *path, /* The path to convert. */
  214.     FSSpecPtr fileSpecPtr) /* On return the spec for the path. */
  215. {
  216. return FSpLocationFromPathAlias(length, path, fileSpecPtr, FALSE);
  217. }
  218. static int
  219. FSpLocationFromPathAlias(
  220.     int length, /* Length of path. */
  221.     CONST char *path, /* The path to convert. */
  222.     FSSpecPtr fileSpecPtr, /* On return the spec for the path. */
  223.     Boolean resolveLink) /* Resolve the last path component? */
  224. {
  225.     Str255 fileName;
  226.     OSErr err;
  227.     short vRefNum;
  228.     long dirID;
  229.     int pos, cur;
  230.     Boolean isDirectory;
  231.     Boolean wasAlias=FALSE;
  232.     FSSpec lastFileSpec;
  233.     /*
  234.      * Check to see if this is a full path.  If partial
  235.      * we assume that path starts with the current working
  236.      * directory.  (Ie. volume & dir = 0)
  237.      */
  238.     vRefNum = 0;
  239.     dirID = 0;
  240.     cur = 0;
  241.     if (length == 0) {
  242.         return fnfErr;
  243.     }
  244.     if (path[cur] == ':') {
  245. cur++;
  246. if (cur >= length) {
  247.     /*
  248.      * If path = ":", just return current directory.
  249.      */
  250.     FSMakeFSSpecCompat(0, 0, NULL, fileSpecPtr);
  251.     return noErr;
  252. }
  253.     } else {
  254. while (path[cur] != ':' && cur < length) {
  255.     cur++;
  256. }
  257. if (cur > 255) {
  258.     return bdNamErr;
  259. }
  260. if (cur < length) {
  261.     /*
  262.      * This is a full path
  263.      */
  264.     cur++;
  265.     strncpy((char *) fileName + 1, path, cur);
  266.     fileName[0] = cur;
  267.     err = FSMakeFSSpecCompat(0, 0, fileName, fileSpecPtr);
  268.     if (err != noErr) return err;
  269.     FSpGetDirectoryID(fileSpecPtr, &dirID, &isDirectory);
  270.     vRefNum = fileSpecPtr->vRefNum;
  271. } else {
  272.     cur = 0;
  273. }
  274.     }
  275.     
  276.     isDirectory = 1;
  277.     while (cur < length) {
  278. if (!isDirectory) {
  279.     return dirNFErr;
  280. }
  281. pos = cur;
  282. while (path[pos] != ':' && pos < length) {
  283.     pos++;
  284. }
  285. if (pos == cur) {
  286.     /* Move up one dir */
  287.     /* cur++; */
  288.     strcpy((char *) fileName + 1, "::");
  289.     fileName[0] = 2;
  290. } else if (pos - cur > 255) {
  291.     return bdNamErr;
  292. } else {
  293.     strncpy((char *) fileName + 1, &path[cur], pos - cur);
  294.     fileName[0] = pos - cur;
  295. }
  296. err = FSMakeFSSpecCompat(vRefNum, dirID, fileName, fileSpecPtr);
  297. if (err != noErr) return err;
  298. lastFileSpec=*fileSpecPtr;
  299. err = ResolveAliasFile(fileSpecPtr, true, &isDirectory, &wasAlias);
  300. if (err != noErr) {
  301.     /* ignore alias resolve errors on last path component */
  302.     if (pos < length) return err;
  303.     else *fileSpecPtr=lastFileSpec;
  304. }
  305. FSpGetDirectoryID(fileSpecPtr, &dirID, &isDirectory);
  306. vRefNum = fileSpecPtr->vRefNum;
  307. cur = pos;
  308. if (path[cur] == ':') {
  309.     cur++;
  310. }
  311.     }
  312.     
  313.     if(!resolveLink && wasAlias)
  314.      *fileSpecPtr=lastFileSpec;
  315.     
  316.     return noErr;
  317. }
  318. /*
  319.  *----------------------------------------------------------------------
  320.  *
  321.  * FSpPathFromLocation --
  322.  *
  323.  * This function obtains a full path name for a given macintosh
  324.  * FSSpec.  Unlike the More Files function FSpGetFullPath, this
  325.  * function will return a C string in the Handle.  It also will
  326.  * create paths for FSSpec that do not yet exist.
  327.  *
  328.  * Results:
  329.  * OSErr code.
  330.  *
  331.  * Side effects:
  332.  * None.
  333.  *
  334.  *----------------------------------------------------------------------
  335.  */
  336. OSErr
  337. FSpPathFromLocation(
  338.     FSSpec *spec, /* The location we want a path for. */
  339.     int *length, /* Length of the resulting path. */
  340.     Handle *fullPath) /* Handle to path. */
  341. {
  342.     OSErr err;
  343.     FSSpec tempSpec;
  344.     CInfoPBRec pb;
  345.     *fullPath = NULL;
  346.     /* 
  347.      * Make a copy of the input FSSpec that can be modified.
  348.      */
  349.     BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
  350.     if (tempSpec.parID == fsRtParID) {
  351. /* 
  352.  * The object is a volume.  Add a colon to make it a full 
  353.  * pathname.  Allocate a handle for it and we are done.
  354.  */
  355. tempSpec.name[0] += 2;
  356. tempSpec.name[tempSpec.name[0] - 1] = ':';
  357. tempSpec.name[tempSpec.name[0]] = '';
  358. err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
  359.     } else {
  360. /* 
  361.  * The object isn't a volume.  Is the object a file or a directory? 
  362.  */
  363. pb.dirInfo.ioNamePtr = tempSpec.name;
  364. pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
  365. pb.dirInfo.ioDrDirID = tempSpec.parID;
  366. pb.dirInfo.ioFDirIndex = 0;
  367. err = PBGetCatInfoSync(&pb);
  368. if ((err == noErr) || (err == fnfErr)) {
  369.     /* 
  370.      * If the file doesn't currently exist we start over.  If the
  371.      * directory exists everything will work just fine.  Otherwise we
  372.      * will just fail later.  If the object is a directory, append a
  373.      * colon so full pathname ends with colon, but only if the name is
  374.      * not empty.  NavServices returns FSSpec's with the parent ID set,
  375.      * but the name empty...
  376.      */
  377.     if (err == fnfErr) {
  378. BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
  379.     } else if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 ) {
  380.         if (tempSpec.name[0] > 0) {
  381.     tempSpec.name[0] += 1;
  382.     tempSpec.name[tempSpec.name[0]] = ':';
  383. }
  384.     }
  385.     /* 
  386.      * Create a new Handle for the object - make it a C string.
  387.      */
  388.     tempSpec.name[0] += 1;
  389.     tempSpec.name[tempSpec.name[0]] = '';
  390.     err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
  391.     if (err == noErr) {
  392. /* 
  393.  * Get the ancestor directory names - loop until we have an 
  394.  * error or find the root directory.
  395.  */
  396. pb.dirInfo.ioNamePtr = tempSpec.name;
  397. pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
  398. pb.dirInfo.ioDrParID = tempSpec.parID;
  399. do {
  400.     pb.dirInfo.ioFDirIndex = -1;
  401.     pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
  402.     err = PBGetCatInfoSync(&pb);
  403.     if (err == noErr) {
  404. /* 
  405.  * Append colon to directory name and add 
  406.  * directory name to beginning of fullPath.
  407.  */
  408. ++tempSpec.name[0];
  409. tempSpec.name[tempSpec.name[0]] = ':';
  410. (void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1],
  411. tempSpec.name[0]);
  412. err = MemError();
  413.     }
  414. } while ( (err == noErr) &&
  415. (pb.dirInfo.ioDrDirID != fsRtDirID) );
  416.     }
  417. }
  418.     }
  419.     
  420.     /*
  421.      * On error Dispose the handle, set it to NULL & return the err.
  422.      * Otherwise, set the length & return.
  423.      */
  424.     if (err == noErr) {
  425. *length = GetHandleSize(*fullPath) - 1;
  426.     } else {
  427. if ( *fullPath != NULL ) {
  428.     DisposeHandle(*fullPath);
  429. }
  430. *fullPath = NULL;
  431. *length = 0;
  432.     }
  433.     return err;
  434. }
  435. /*
  436.  *----------------------------------------------------------------------
  437.  *
  438.  * GetGlobalMouseTcl --
  439.  *
  440.  * This procedure obtains the current mouse position in global
  441.  * coordinates.
  442.  *
  443.  * Results:
  444.  * None.
  445.  *
  446.  * Side effects:
  447.  * None.
  448.  *
  449.  *----------------------------------------------------------------------
  450.  */
  451. void
  452. GetGlobalMouseTcl(
  453.     Point *mouse) /* Mouse position. */
  454. {
  455.     EventRecord event;
  456.     
  457.     OSEventAvail(0, &event);
  458.     *mouse = event.where;
  459. }
  460. pascal OSErr FSpGetDirectoryIDTcl (CONST FSSpec * spec, 
  461. long * theDirID, Boolean * isDirectory)
  462. {
  463. return(FSpGetDirectoryID(spec, theDirID, isDirectory));
  464. }
  465. pascal short FSpOpenResFileCompatTcl (CONST FSSpec * spec, SignedByte permission)
  466. {
  467. return(FSpOpenResFileCompat(spec,permission));
  468. }
  469. pascal void FSpCreateResFileCompatTcl (
  470. CONST FSSpec * spec, OSType creator, 
  471. OSType fileType, ScriptCode scriptTag)
  472. {
  473. FSpCreateResFileCompat (spec,creator,fileType,scriptTag);
  474. }