syncfiles/macos/choose_directory.c
Dietrich Epp b1bcae531b Rework error handling
Previously, various error handling functions were defined, but not all
of them were even used. The new error handling functions handle the most
common cases:

- Assertions. These can be handled with `ASSERT()`, which gives the
  error location for debugging.

- Errors we don't know how to handle, like GetNewWindow returning NULL.
  These can be handled with `EXIT_INTERNAL()`, which gives the error
  location for debugging.

- Out of memory conditions. These can be handled with `ShowMemError()`.

- System errors in response to user operations. These can be handled
  with `ShowError()`.
2023-05-06 19:41:40 -04:00

110 lines
2.7 KiB
C

// Copyright 2022 Dietrich Epp.
// This file is part of SyncFiles. SyncFiles is licensed under the terms of the
// Mozilla Public License, version 2.0. See LICENSE.txt for details.
#include "macos/choose_directory.h"
#include "macos/error.h"
#include "macos/resources.h"
#include "macos/strutil.h"
#include <string.h>
typedef enum {
kCDNone,
kCDChild,
kCDCurrent,
} ChooseDirStatus;
struct ChooseDirReply {
ChooseDirStatus status;
FSSpec *directory;
};
// FIXME: Don't use pascal on PowerMac.
static pascal Boolean ChooseDirectoryFileFilter(CInfoPBPtr pb,
void *yourDataPtr)
{
(void)yourDataPtr;
return (pb->hFileInfo.ioFlAttrib & ioDirMask) == 0;
}
enum {
kCDItemChoose = 10,
kCDItemChooseCurrent = 11,
};
static void SelectCurrentDirectory(struct ChooseDirReply *reply)
{
CInfoPBRec ci;
OSStatus err;
Str63 name;
FSSpec *directory;
memset(&ci, 0, sizeof(ci));
ci.dirInfo.ioNamePtr = name;
ci.dirInfo.ioVRefNum = -LMGetSFSaveDisk();
ci.dirInfo.ioFDirIndex = -1;
ci.dirInfo.ioDrDirID = LMGetCurDirStore();
err = PBGetCatInfoSync(&ci);
if (err != 0) {
ShowError(kErrNone, kErrNone, err, NULL);
return;
}
directory = reply->directory;
directory->vRefNum = ci.dirInfo.ioVRefNum;
directory->parID = ci.dirInfo.ioDrParID;
StrCopy(directory->name, sizeof(directory->name), name);
reply->status = kCDCurrent;
}
static pascal short ChooseDirectoryDialogHook(short item, DialogRef theDialog,
void *yourDataPtr)
{
struct ChooseDirReply *reply;
if (GetWRefCon((WindowRef)theDialog) != sfMainDialogRefCon) {
return item;
}
reply = yourDataPtr;
switch (item) {
case kCDItemChoose:
reply->status = kCDChild;
return sfItemCancelButton;
case kCDItemChooseCurrent:
SelectCurrentDirectory(yourDataPtr);
return sfItemCancelButton;
default:
return item;
}
}
Boolean ChooseDirectory(FSSpec *directory)
{
struct ChooseDirReply cdreply;
FileFilterYDUPP fileFilter;
DlgHookYDUPP dlgHook;
StandardFileReply sfreply;
Point where;
cdreply.status = kCDNone;
cdreply.directory = directory;
fileFilter = NewFileFilterYDProc(ChooseDirectoryFileFilter);
ASSERT(fileFilter != NULL);
dlgHook = NewDlgHookYDProc(ChooseDirectoryDialogHook);
ASSERT(dlgHook != NULL);
where.v = -1;
where.h = -1;
CustomGetFile(fileFilter, -1, NULL, &sfreply, rDLOG_OpenFolder, where,
dlgHook, NULL /* filterProc */, 0, NULL, &cdreply);
// DisposeFileFilterYDUPP(fileFilter);
// DisposeDlgHookYDUPP(dlgHook);
switch (cdreply.status) {
case kCDChild:
BlockMoveData(&sfreply.sfFile, directory, sizeof(FSSpec));
return true;
case kCDCurrent:
return true;
default:
return false;
}
}