home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Tcl-Tk 8.0 / Pre-installed version / tcl8.0 / mac / tclMacUtil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-15  |  10.3 KB  |  442 lines  |  [TEXT/CWIE]

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