Rather more natural (if much more complex) Mac Filename implementation.

Filenames are represented as a FSSpec, which is converted to and from an
alias record ('alis' resource) when saving and loading sessions.
.
It might be an idea to allow in-core Filenames to contain alias records too,
so that they can refer to directories that don't exist on the current system,
but that requires Filenames to be dynamically allocated, which is likely to be
a pain.

[originally from svn r2771]
This commit is contained in:
Ben Harris 2003-02-01 21:44:05 +00:00
Родитель 4f76d033d5
Коммит 61711b9594
3 изменённых файлов: 155 добавлений и 15 удалений

Просмотреть файл

@ -1,4 +1,4 @@
/* $Id: mac.c,v 1.40 2003/02/01 17:24:26 simon Exp $ */ /* $Id: mac.c,v 1.41 2003/02/01 21:44:05 ben Exp $ */
/* /*
* Copyright (c) 1999 Ben Harris * Copyright (c) 1999 Ben Harris
* All rights reserved. * All rights reserved.
@ -771,9 +771,9 @@ Filename platform_default_filename(const char *name)
{ {
Filename ret; Filename ret;
if (!strcmp(name, "LogFileName")) if (!strcmp(name, "LogFileName"))
strcpy(ret.path, "putty.log"); FSMakeFSSpec(0, 0, "\pputty.log", &ret.fss);
else else
*ret.path = '\0'; memset(&ret, 0, sizeof(ret));
return ret; return ret;
} }
@ -804,24 +804,80 @@ void platform_get_x11_auth(char *display, int *proto,
Filename filename_from_str(const char *str) Filename filename_from_str(const char *str)
{ {
Filename ret; Filename ret;
strncpy(ret.path, str, sizeof(ret.path)); Str255 tmp;
ret.path[sizeof(ret.path)-1] = '\0';
/* XXX This fails for filenames over 255 characters long. */
c2pstrcpy(tmp, str);
FSMakeFSSpec(0, 0, tmp, &ret.fss);
return ret; return ret;
} }
/*
* Convert a filename to a string for display purposes.
* See pp 2-44--2-46 of IM:Files
*
* XXX static storage considered harmful
*/
const char *filename_to_str(const Filename *fn) const char *filename_to_str(const Filename *fn)
{ {
return fn->path; CInfoPBRec pb;
Str255 dirname;
OSErr err;
static char *path = NULL;
char *newpath;
if (path != NULL) sfree(path);
path = smalloc(fn->fss.name[0]);
p2cstrcpy(path, fn->fss.name);
pb.dirInfo.ioNamePtr = dirname;
pb.dirInfo.ioVRefNum = fn->fss.vRefNum;
pb.dirInfo.ioDrParID = fn->fss.parID;
pb.dirInfo.ioFDirIndex = -1;
do {
pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
err = PBGetCatInfoSync(&pb);
/* XXX Assume not A/UX */
newpath = smalloc(strlen(path) + dirname[0] + 2);
p2cstrcpy(newpath, dirname);
strcat(newpath, ":");
strcat(newpath, path);
sfree(path);
path = newpath;
} while (pb.dirInfo.ioDrDirID != fsRtDirID);
return path;
} }
int filename_equal(Filename f1, Filename f2) int filename_equal(Filename f1, Filename f2)
{ {
return !strcmp(f1.path, f2.path);
return f1.fss.vRefNum == f2.fss.vRefNum &&
f1.fss.parID == f2.fss.parID &&
f1.fss.name[0] == f2.fss.name[0] &&
memcmp(f1.fss.name + 1, f2.fss.name + 1, f1.fss.name[0]) == 0;
} }
int filename_is_null(Filename fn) int filename_is_null(Filename fn)
{ {
return !*fn.path;
return fn.fss.vRefNum == 0 && fn.fss.parID == 0 && fn.fss.name[0] == 0;
}
FILE *f_open(Filename fn, char const *mode)
{
short savevol;
long savedir;
char tmp[256];
FILE *ret;
HGetVol(NULL, &savevol, &savedir);
if (HSetVol(NULL, fn.fss.vRefNum, fn.fss.parID) == noErr) {
p2cstrcpy(tmp, fn.fss.name);
ret = fopen(tmp, mode);
} else
ret = NULL;
HSetVol(NULL, savevol, savedir);
return ret;
} }
/* /*

Просмотреть файл

@ -1,4 +1,4 @@
/* $Id: macstore.c,v 1.14 2003/02/01 15:44:08 ben Exp $ */ /* $Id: macstore.c,v 1.15 2003/02/01 21:44:05 ben Exp $ */
/* /*
* macstore.c: Macintosh-specific impementation of the interface * macstore.c: Macintosh-specific impementation of the interface
@ -360,12 +360,92 @@ void write_setting_fontspec(void *handle, const char *name, FontSpec font)
int read_setting_filename(void *handle, const char *name, Filename *result) int read_setting_filename(void *handle, const char *name, Filename *result)
{ {
return !!read_setting_s(handle, name, result->path, sizeof(result->path)); int fd;
AliasHandle h;
Boolean changed;
OSErr err;
if (handle == NULL) goto out;
fd = *(int *)handle;
UseResFile(fd);
if (ResError() != noErr) goto out;
h = (AliasHandle)get1namedresource(rAliasType, name);
if (h == NULL) goto out;
if ((*h)->userType == 'pTTY' && (*h)->aliasSize == sizeof(**h))
memset(result, 0, sizeof(*result));
else {
err = ResolveAlias(NULL, h, &result->fss, &changed);
if (err != noErr && err != fnfErr) goto out;
if ((*h)->userType == 'pTTY') {
long dirid;
StrFileName fname;
/* Tail of record is pascal string contaning leafname */
if (FSpGetDirID(&result->fss, &dirid, FALSE) != noErr) goto out;
memcpy(fname, (char *)*h + (*h)->aliasSize,
GetHandleSize((Handle)h) - (*h)->aliasSize);
err = FSMakeFSSpec(result->fss.vRefNum, dirid, fname,
&result->fss);
if (err != noErr && err != fnfErr) goto out;
}
}
ReleaseResource((Handle)h);
if (ResError() != noErr) goto out;
return 1;
out:
return 0;
} }
void write_setting_filename(void *handle, const char *name, Filename result) void write_setting_filename(void *handle, const char *name, Filename fn)
{ {
write_setting_s(handle, name, result.path); int fd = *(int *)handle;
AliasHandle h;
int id;
OSErr error;
UseResFile(fd);
if (ResError() != noErr)
fatalbox("Failed to open saved session (%d)", ResError());
if (filename_is_null(fn)) {
/* Generate a special "null" alias */
h = (AliasHandle)NewHandle(sizeof(**h));
if (h == NULL)
fatalbox("Failed to create fake alias");
(*h)->userType = 'pTTY';
(*h)->aliasSize = sizeof(**h);
} else {
error = NewAlias(NULL, &fn.fss, &h);
if (error == fnfErr) {
/*
* NewAlias can't create an alias for a nonexistent file.
* Create an alias for the directory, and record the
* filename as well.
*/
FSSpec tmpfss;
FSMakeFSSpec(fn.fss.vRefNum, fn.fss.parID, NULL, &tmpfss);
error = NewAlias(NULL, &tmpfss, &h);
if (error != noErr)
fatalbox("Failed to create alias");
(*h)->userType = 'pTTY';
SetHandleSize((Handle)h, (*h)->aliasSize + fn.fss.name[0] + 1);
if (MemError() != noErr)
fatalbox("Failed to create alias");
memcpy((char *)*h + (*h)->aliasSize, fn.fss.name,
fn.fss.name[0] + 1);
}
if (error != noErr)
fatalbox("Failed to create alias");
}
/* Put the data in a resource. */
id = Unique1ID(rAliasType);
if (ResError() != noErr)
fatalbox("Failed to get ID for resource %s (%d)", name, ResError());
addresource((Handle)h, rAliasType, id, name);
if (ResError() != noErr)
fatalbox("Failed to add resource %s (%d)", name, ResError());
} }
void close_settings_r(void *handle) { void close_settings_r(void *handle) {

Просмотреть файл

@ -5,17 +5,21 @@
typedef void *Context; /* FIXME */ typedef void *Context; /* FIXME */
#include <MacTypes.h> #include <MacTypes.h>
#include <stdio.h> /* for FILENAME_MAX */ #include <Files.h>
#include <stdio.h>
struct Filename { struct Filename {
char path[FILENAME_MAX]; FSSpec fss;
}; };
#define f_open(filename, mode) ( fopen((filename).path, (mode)) )
extern FILE * f_open(struct Filename, char const *);
/* Suspiciously similar to an ICFontRecord */ /* Suspiciously similar to an ICFontRecord */
struct FontSpec { struct FontSpec {
short size; short size;
Style face; Style face;
char pad;
Str255 name; Str255 name;
}; };