I wrote a library for Navigation services which is easier to use than StandardFile.
It's the simplest solution that I have ever seen.
All references to Apple events have been removed.
This is now part of the OS 9.3 SDK.
class SimpleNavigation
{
public:
// Global functions.
static Bool Init_class();
static Bool Exit_class();
static Bool CheckIsInFront(bool &isInFront);
static Bool AskDiscardChanges(NavEventUPP eventProc,
bool &ok);
static Bool AskSaveChanges(NavEventUPP eventProc,
NavAskSaveChangesAction action,
NavAskSaveChangesResult &reply);
static Bool ChooseFile(NavEventUPP eventProc,
NavTypeListHandle typeList,
bool &ok,
FSSpec &file);
static Bool ChooseFiles(NavEventUPP eventProc,
NavTypeListHandle typeList,
SInt32 maxFiles,
bool &ok,
SInt32 &cFiles,
FSSpec *files);
static Bool ChooseFolder(NavEventUPP eventProc,
bool &ok,
FSSpec &folder);
static Bool ChooseObject(NavEventUPP eventProc,
bool &ok,
FSSpec &object);
static Bool ChooseVolume(NavEventUPP eventProc,
bool &ok,
FSSpec &volume);
static Bool GetFile(NavEventUPP eventProc,
NavTypeListHandle typeList,
bool &ok,
FSSpec &file);
static Bool GetFiles(NavEventUPP eventProc,
NavTypeListHandle typeList,
SInt32 maxFiles,
bool &ok,
SInt32 &cFiles,
FSSpec *files);
static Bool NewFolder(NavEventUPP eventProc,
bool &ok,
FSSpec &folder);
static Bool PutFile(NavEventUPP eventProc,
OSType fileType,
OSType fileCreator,
bool &ok,
FSSpec &file);
// Forbidden.
private:
SimpleNavigation();
};
int main()
{
ConsoleError::Init_class();
cout << "Start.";
cout << endl;
#ifdef __DEBUG__
Error::Show("\pDebug version");
#endif
if (!Profile())
{
Return_0("\pProfile fails");
}
cout << "Finish.";
cout << endl;
return 0;
}
Bool Profile()
{
#ifdef __USE_PROFILER__
::ProfilerInit(0,
4,
5000,
100);
#endif
const Bool ok=SimpleNavigationTest();
#ifdef __USE_PROFILER__
::ProfilerDump("\pProfiler");
::ProfilerTerm();
#endif
if (!ok)
{
Return_false("\pSimpleNavigationTest fails");
}
return True;
}
#ifdef __USE_PROFILER__
#pragma profile on
#endif
pascal void NavEvent(NavEventCallbackMessage const callBackSelector,
NavCBRec* const callBackParms,
void*)
{
// Rem: this function is necessary
// if you want to move and resize your dialogs,
// and update background windows.
if (callBackSelector==kNavCBEvent)
{
if (!::SIOUXHandleOneEvent(callBackParms->eventData.eventDataParms.event))
{
// Rem: the event was handled by SIOUX.
}
}
}
Bool SimpleNavigationTest()
{
if (!SimpleNavigation::Init_class())
{
Return_false("\pInit SimpleNavigation class fails");
}
NavEventUPP const eventProc=NewNavEventUPP(NavEvent);
const Bool ok=TryEveryDialog(eventProc);
DisposeNavEventUPP(eventProc);
if (!SimpleNavigation::Exit_class())
{
Return_false("\pExit SimpleNavigation class fails");
}
if (!ok)
{
Return_false("\pTry every dialog fails");
}
return True;
}
Bool MakeTypeList(NavTypeListHandle &typeList)
{
const SInt16 typeCount=6;
Handle h;
if (!BoolMemory::NewHandle(sizeof(NavTypeList)+(typeCount-1)*sizeof(OSType),
h))
{
Return_false("\pNewHandle fails");
}
typeList=reinterpret_cast<NavTypeListHandle>(h);
(**typeList).componentSignature='BOBO';
(**typeList).reserved=0;
(**typeList).osTypeCount=typeCount;
(**typeList).osType[0]='CWWP'; // Rem: text processing.
(**typeList).osType[1]='CWGR'; // Rem: drawing.
(**typeList).osType[2]='CWPT'; // Rem: paint.
(**typeList).osType[3]='CWSS'; // Rem: spreadsheet.
(**typeList).osType[4]='CWDB'; // Rem: database.
(**typeList).osType[5]='CWCM'; // Rem: communications.
return True;
}
Bool DeleteTypeLijst(NavTypeListHandle &typeList)
{
Handle const h=reinterpret_cast<Handle>(typeList);
if (!BoolMemory::DisposeHandle(h))
{
Return_false("\pDisposeHandle fails");
}
typeList=nil;
return True;
}
Bool WaitUntilProgramIsInFront()
{
bool isInFront;
do
{
if (!SimpleNavigation::CheckIsInFront(isInFront))
{
Return_false("\pCheckIsInFront fails");
}
EventRecord event;
const bool hasEvent=::WaitNextEvent(everyEvent,
&event,
6,
nil);
if (hasEvent)
{
if (!::SIOUXHandleOneEvent(&event))
{
// Rem: the event was handled by SIOUX.
}
}
}
while (!isInFront);
return True;
}
Bool TryEveryDialog(NavEventUPP const eventProc)
{
if (true)
{
if (!Test_AskDiscardChanges(eventProc))
{
Return_false("\pTest_AskDiscardChanges fails");
}
}
if (true)
{
if (!Test_AskSaveChanges(eventProc))
{
Return_false("\pTest_AskSaveChanges fails");
}
}
if (true)
{
if (!Test_ChooseFile(eventProc))
{
Return_false("\pTest_ChooseFile fails");
}
}
if (true)
{
if (!Test_ChooseFiles(eventProc))
{
Return_false("\pTest_ChooseFiles fails");
}
}
if (true)
{
if (!Test_ChooseFolder(eventProc))
{
Return_false("\pTest_ChooseFolder fails");
}
}
if (true)
{
if (!Test_ChooseObject(eventProc))
{
Return_false("\pTest_ChooseObject fails");
}
}
if (true)
{
if (!Test_ChooseVolume(eventProc))
{
Return_false("\pTest_ChooseVolume fails");
}
}
if (true)
{
if (!Test_GetFile(eventProc))
{
Return_false("\pTest_GetFile fails");
}
}
if (true)
{
if (!Test_GetFiles(eventProc))
{
Return_false("\pTest_GetFiles fails");
}
}
if (true)
{
if (!Test_NewFolder(eventProc))
{
Return_false("\pTest_NewFolder fails");
}
}
if (true)
{
if (!Test_PutFile(eventProc))
{
Return_false("\pTest_PutFile fails");
}
}
return True;
}
Bool Test_AskDiscardChanges(NavEventUPP const eventProc)
{
if (!WaitUntilProgramIsInFront())
{
Return_false("\pWait until program is in front fails");
}
bool ok;
if (!SimpleNavigation::AskDiscardChanges(eventProc,
ok))
{
Return_false("\pAskDiscardChanges fails");
}
return True;
}
Bool Test_AskSaveChanges(NavEventUPP const eventProc)
{
if (!WaitUntilProgramIsInFront())
{
Return_false("\pWait until program is in front fails");
}
NavAskSaveChangesResult reply;
if (!SimpleNavigation::AskSaveChanges(eventProc,
kNavSaveChangesOther,
reply))
{
Return_false("\pAskSaveChanges fails");
}
if (!SimpleNavigation::AskSaveChanges(eventProc,
kNavSaveChangesClosingDocument,
reply))
{
Return_false("\pAskSaveChanges fails");
}
if (!SimpleNavigation::AskSaveChanges(eventProc,
kNavSaveChangesQuittingApplication,
reply))
{
Return_false("\pAskSaveChanges fails");
}
return True;
}
Bool Test_ChooseFile(NavEventUPP const eventProc)
{
NavTypeListHandle typeList;
if (!MakeTypeList(typeList))
{
Return_false("\pMake type list fails");
}
const Bool ok=Test_ChooseFile(eventProc,
typeList);
if (!DeleteTypeLijst(typeList))
{
Return_false("\pDelete type list fails");
}
if (!ok)
{
Return_false("\pTest_ChooseFile fails");
}
return True;
}
Bool Test_ChooseFile(NavEventUPP const eventProc,
NavTypeListHandle const typeList)
{
if (!WaitUntilProgramIsInFront())
{
Return_false("\pWait until program is in front fails");
}
bool ok;
FSSpec file;
if (!SimpleNavigation::ChooseFile(eventProc,
typeList,
ok,
file))
{
Return_false("\pChooseFile fails");
}
return True;
}
Bool Test_ChooseFiles(NavEventUPP const eventProc)
{
NavTypeListHandle typeList;
if (!MakeTypeList(typeList))
{
Return_false("\pMake type list fails");
}
const Bool ok=Test_ChooseFiles(eventProc,
typeList);
if (!DeleteTypeLijst(typeList))
{
Return_false("\pDelete type list fails");
}
if (!ok)
{
Return_false("\pTest_ChooseFiles fails");
}
return True;
}
Bool Test_ChooseFiles(NavEventUPP const eventProc,
NavTypeListHandle const typeList)
{
if (!WaitUntilProgramIsInFront())
{
Return_false("\pWait until program is in front fails");
}
const SInt32 maxFiles=5;
bool ok;
SInt32 cFiles;
FSSpec files[maxFiles];
if (!SimpleNavigation::ChooseFiles(eventProc,
typeList,
maxFiles,
ok,
cFiles,
files))
{
Return_false("\pChooseFiles fails");
}
return True;
}
Bool Test_ChooseFolder(NavEventUPP const eventProc)
{
if (!WaitUntilProgramIsInFront())
{
Return_false("\pWait until program is in front fails");
}
bool ok;
FSSpec folder;
if (!SimpleNavigation::ChooseFolder(eventProc,
ok,
folder))
{
Return_false("\pChooseFolder fails");
}
return True;
}
Bool Test_ChooseObject(NavEventUPP const eventProc)
{
if (!WaitUntilProgramIsInFront())
{
Return_false("\pWait until program is in front fails");
}
bool ok;
FSSpec object;
if (!SimpleNavigation::ChooseObject(eventProc,
ok,
object))
{
Return_false("\pChooseObject fails");
}
return True;
}
Bool Test_ChooseVolume(NavEventUPP const eventProc)
{
if (!WaitUntilProgramIsInFront())
{
Return_false("\pWait until program is in front fails");
}
bool ok;
FSSpec volume;
if (!SimpleNavigation::ChooseVolume(eventProc,
ok,
volume))
{
Return_false("\pChooseVolume fails");
}
return True;
}
Bool Test_GetFile(NavEventUPP const eventProc)
{
NavTypeListHandle typeList;
if (!MakeTypeList(typeList))
{
Return_false("\pMake type list fails");
}
const Bool ok=Test_GetFile(eventProc,
typeList);
if (!DeleteTypeLijst(typeList))
{
Return_false("\pDelete type list fails");
}
if (!ok)
{
Return_false("\pTest_GetFile fails");
}
return True;
}
Bool Test_GetFile(NavEventUPP const eventProc,
NavTypeListHandle const typeList)
{
if (!WaitUntilProgramIsInFront())
{
Return_false("\pWait until program is in front fails");
}
bool ok;
FSSpec file;
if (!SimpleNavigation::GetFile(eventProc,
typeList,
ok,
file))
{
Return_false("\pGetFile fails");
}
return True;
}
Bool Test_GetFiles(NavEventUPP const eventProc)
{
NavTypeListHandle typeList;
if (!MakeTypeList(typeList))
{
Return_false("\pMake type list fails");
}
const Bool ok=Test_GetFiles(eventProc,
typeList);
if (!DeleteTypeLijst(typeList))
{
Return_false("\pDelete type list fails");
}
if (!ok)
{
Return_false("\pTest_GetFiles fails");
}
return True;
}
Bool Test_GetFiles(NavEventUPP const eventProc,
NavTypeListHandle const typeList)
{
if (!WaitUntilProgramIsInFront())
{
Return_false("\pWait until program is in front fails");
}
const SInt32 maxFiles=5;
bool ok;
SInt32 cFiles;
FSSpec files[maxFiles];
if (!SimpleNavigation::GetFiles(eventProc,
typeList,
maxFiles,
ok,
cFiles,
files))
{
Return_false("\pGetFiles fails");
}
return True;
}
Bool Test_NewFolder(NavEventUPP const eventProc)
{
if (!WaitUntilProgramIsInFront())
{
Return_false("\pWait until program is in front fails");
}
bool ok;
FSSpec folder;
if (!SimpleNavigation::NewFolder(eventProc,
ok,
folder))
{
Return_false("\pNewFolder fails");
}
return True;
}
Bool Test_PutFile(NavEventUPP const eventProc)
{
if (!WaitUntilProgramIsInFront())
{
Return_false("\pWait until program is in front fails");
}
bool ok;
FSSpec file;
if (!SimpleNavigation::PutFile(eventProc,
'PICT',
'ogle',
ok,
file))
{
Return_false("\pPutFile fails");
}
return True;
}
#ifdef __USE_PROFILER__
#pragma profile off
#endif