// 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 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) { ExitErrorOS(kErrUnknown, err); } 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 1; case kCDCurrent: return 1; default: return 0; } }