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