diff options
Diffstat (limited to 'SrcShared/EmDocument.cpp')
-rw-r--r-- | SrcShared/EmDocument.cpp | 1211 |
1 files changed, 1211 insertions, 0 deletions
diff --git a/SrcShared/EmDocument.cpp b/SrcShared/EmDocument.cpp new file mode 100644 index 0000000..2dab9aa --- /dev/null +++ b/SrcShared/EmDocument.cpp @@ -0,0 +1,1211 @@ +/* -*- mode: C++; tab-width: 4 -*- */ +/* ===================================================================== *\ + Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries. + All rights reserved. + + This file is part of the Palm OS Emulator. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +\* ===================================================================== */ + +#include "EmCommon.h" +#include "EmDocument.h" + +#include "EmApplication.h" // SetDocument +#include "EmCommands.h" // EmCommandID, kCommandSessionClose, etc. +#include "EmPatchState.h" // EmPatchState::EvtGetEventCalled +#include "EmRPC.h" // RPC::Idle +#include "EmSession.h" // EmStopMethod +#include "EmWindow.h" // EmWindow, gWindow +#include "ErrorHandling.h" // Errors::ReportIfError +#include "Hordes.h" // Hordes::PostLoad, Suspend, Step, Resume, Stop +#include "Platform.h" // Platform::GetBoundDevice +#include "SocketMessaging.h" // CSocket::IdleAll +#include "Startup.h" // Startup::NewHorde +#include "Strings.r.h" // kStr_CmdClose, etc. + +#if HAS_PROFILING +#include "Profiling.h" // ProfileStart, ProfileStop, ProfileDump +#endif + +EmDocument* gDocument; + +typedef void (EmDocument::*EmCommandFn)(EmCommandID); + + +static const struct +{ + EmCommandID fCommandID; + EmCommandFn fFn; + StrCode fErrStrCode; +} +kCommand[] = +{ + { kCommandSessionSave, &EmDocument::DoSave, kStr_CmdSave }, + { kCommandSessionSaveAs, &EmDocument::DoSaveAs, kStr_CmdSave }, + { kCommandSessionBound, &EmDocument::DoSaveBound, kStr_CmdSaveBound }, + { kCommandScreenSave, &EmDocument::DoSaveScreen, kStr_CmdSaveScreen }, + { kCommandSessionInfo, &EmDocument::DoInfo, kStr_CmdSessionInfo }, + { kCommandImportOther, &EmDocument::DoImport, kStr_CmdInstall }, + { kCommandImport0, &EmDocument::DoImport, kStr_CmdInstall }, + { kCommandImport1, &EmDocument::DoImport, kStr_CmdInstall }, + { kCommandImport2, &EmDocument::DoImport, kStr_CmdInstall }, + { kCommandImport3, &EmDocument::DoImport, kStr_CmdInstall }, + { kCommandImport4, &EmDocument::DoImport, kStr_CmdInstall }, + { kCommandImport5, &EmDocument::DoImport, kStr_CmdInstall }, + { kCommandImport6, &EmDocument::DoImport, kStr_CmdInstall }, + { kCommandImport7, &EmDocument::DoImport, kStr_CmdInstall }, + { kCommandImport8, &EmDocument::DoImport, kStr_CmdInstall }, + { kCommandImport9, &EmDocument::DoImport, kStr_CmdInstall }, + { kCommandExport, &EmDocument::DoExport, kStr_CmdInstall }, + { kCommandHotSync, &EmDocument::DoHotSync, kStr_CmdHotSync }, + { kCommandReset, &EmDocument::DoReset, kStr_CmdReset }, + { kCommandGremlinsNew, &EmDocument::DoGremlinNew, kStr_CmdGremlinNew }, + { kCommandGremlinsSuspend, &EmDocument::DoGremlinSuspend, kStr_CmdGremlinSuspend }, + { kCommandGremlinsStep, &EmDocument::DoGremlinStep, kStr_CmdGremlinStep }, + { kCommandGremlinsResume, &EmDocument::DoGremlinResume, kStr_CmdGremlinResume }, + { kCommandGremlinsStop, &EmDocument::DoGremlinStop, kStr_CmdGremlinStop } + +#if HAS_PROFILING + , + { kCommandProfileStart, &EmDocument::DoProfileStart, kStr_CmdProfileStart }, + { kCommandProfileStop, &EmDocument::DoProfileStop, kStr_CmdProfileStop }, + { kCommandProfileDump, &EmDocument::DoProfileDump, kStr_CmdProfileDump } +#endif +}; + + +class EmActionNewHorde : public EmAction +{ + public: + EmActionNewHorde (const HordeInfo& info) : + EmAction (kStr_CmdGremlinNew), + fInfo (info) + { + } + + virtual ~EmActionNewHorde (void) + { + } + + virtual void Do (void) + { + EmSessionStopper stopper (gSession, kStopOnSysCall); + Hordes::New (fInfo); + } + + private: + HordeInfo fInfo; +}; + + +class EmActionDialog : public EmAction +{ + public: + EmActionDialog (EmDlgThreadFn fn, + const void* parms, + EmDlgItemID& result) : + EmAction (0), + fDlgFn (fn), + fDlgParms (parms), + fDlgResult (result) + { + } + + virtual ~EmActionDialog (void) {} + + virtual void Do (void); + + private: + EmDlgThreadFn fDlgFn; + const void* fDlgParms; + EmDlgItemID& fDlgResult; +}; + + +void EmActionDialog::Do (void) +{ + // Show any error messages from the CPU thread. + + fDlgResult = EmDlg::RunDialog (fDlgFn, fDlgParms); + +#if HAS_OMNI_THREAD + EmAssert (gSession); + gSession->UnblockDialog (); +#endif +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoNew +// --------------------------------------------------------------------------- +// Bottleneck for all document creation. Creates a new document, associates +// it with the given application, creates a new window, creates a new session, +// and sets last configuration and last session preferences accordingly. +// On success, the new document is returned. On failure, an exception is +// thrown. + +EmDocument* EmDocument::DoNew (const Configuration& cfg) +{ + // Create the new document. + + EmDocument* doc = EmDocument::HostCreateDocument (); + + try + { + // Create the new session. + + doc->fSession = new EmSession; + doc->fSession->CreateNew (cfg); + doc->fSession->CreateThread (false); // !!! Created here, but destroyed in EmSession::~EmSession! + + // Save the newly created configuration for next time. + + { + Preference<Configuration> pref (kPrefKeyLastConfiguration); + pref = doc->fSession->GetConfiguration (); + } + + // Zap the last-saved session file, so that we give preference + // to a New operation at startup and not an Open operation. + + { + Preference<EmFileRef> pref (kPrefKeyLastPSF); + pref = EmFileRef(); + } + + // Set the ROM's file type, so that the icon looks right. + + cfg.fROMFile.SetCreatorAndType (kFileCreatorEmulator, kFileTypeROM); + } + catch (...) + { + delete doc; + throw; + } + + // If we got here, then everything worked. Open a window on the session. + + doc->PrvOpenWindow (); + + return doc; +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoOpen +// --------------------------------------------------------------------------- +// Bottleneck for all document opening. Creates a new document, associates +// it with the given application, creates a new window, opens an old session, +// and sets last configuration and last session preferences accordingly. +// On success, the new document is returned. On failure, an exception is +// thrown. + +EmDocument* EmDocument::DoOpen (const EmFileRef& file) +{ + // Create the new document. + + Bool hordesIsOn = false; + EmDocument* doc = EmDocument::HostCreateDocument (); + + try + { + // Open the old session. + + doc->fSession = new EmSession; + doc->fFile = file; // !!! Actually, this is redundant with EmSession's. + doc->fSession->CreateOld (file); + + // Get this here before we start up the thread. If we were to first + // start up the thread, it would proceed to run the Gremlin, which + // may temporarily turn off the "Gremlins is running" flag (see + // Hordes::SaveRootState), which would lead us to not open the + // Gremlin Control Window. + + hordesIsOn = Hordes::IsOn (); + + doc->fSession->CreateThread (false); // !!! Created here, but destroyed in EmSession::~EmSession! + + // Patch up anything for Hordes. + + Hordes::PostLoad (); + + // Save the newly created configuration for next time. + + { + Preference<Configuration> pref (kPrefKeyLastConfiguration); + pref = doc->fSession->GetConfiguration (); + } + + // Save the last-opened session file for next time. + + { + Preference<EmFileRef> pref (kPrefKeyLastPSF); + pref = file; + } + + // Update the session MRU list. + + gEmuPrefs->UpdateRAMMRU (file); + } + catch (...) + { + delete doc; + throw; + } + + // If we got here, then everything worked. Open a window on the session. + + doc->PrvOpenWindow (); + + // If we loaded a session file with a Gremlin running, make sure + // the Gremlin control window is open. Do this after opening the + // LCD window so that the Gremlin window is properly a child window + // of the LCD window. + + if (hordesIsOn) + { + EmDlg::GremlinControlOpen (); + } + + return doc; +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoNewBound +// --------------------------------------------------------------------------- + +EmDocument* EmDocument::DoNewBound (void) +{ + EmAssert (gApplication->IsBoundPartially ()); + + // Create the new document. + + EmDocument* doc = EmDocument::HostCreateDocument (); + + try + { + // Create the new session. + + doc->fSession = new EmSession; + doc->fSession->CreateBound (); + doc->fSession->CreateThread (false); // !!! Created here, but destroyed in EmSession::~EmSession! + } + catch (...) + { + delete doc; + throw; + } + + // If we got here, then everything worked. Open a window on the session. + + doc->PrvOpenWindow (); + + return doc; +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoOpenBound +// --------------------------------------------------------------------------- + +EmDocument* EmDocument::DoOpenBound (void) +{ + EmAssert (gApplication->IsBoundFully ()); + + EmDocument* doc = EmDocument::HostCreateDocument (); + + try + { + doc->fSession = new EmSession; + doc->fSession->CreateBound (); + doc->fSession->CreateThread (false); // !!! Created here, but destroyed in EmSession::~EmSession! + } + catch (...) + { + delete doc; + throw; + } + + // If we got here, then everything worked. Open a window on the session. + + doc->PrvOpenWindow (); + + return doc; +} + + +#pragma mark - + +// --------------------------------------------------------------------------- +// ¥ EmDocument::EmDocument +// --------------------------------------------------------------------------- +// Constructor. Set our data members to NULL, and set the global application +// variable to point to us. + +EmDocument::EmDocument (void) : + EmActionHandler (), + fSession (NULL), + fFile () +{ + EmAssert (gDocument == NULL); + gDocument = this; +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::~EmDocument +// --------------------------------------------------------------------------- +// Destructor. Close the Gremlin Control window, disassociate us from the +// application object, clear the global document variable, and delete the +// session object. +// +// Note that we don't close the window object here. We defer that to any +// document subclass in case it's not appropriate to close the window for +// this platform (for instance, the window stays open on Unix). + +EmDocument::~EmDocument (void) +{ + EmDlg::GremlinControlClose (); + + EmAssert (gDocument == this); + gDocument = NULL; + + delete fSession; +} + + +#pragma mark - + +// --------------------------------------------------------------------------- +// ¥ EmDocument::HandleCommand +// --------------------------------------------------------------------------- +// Handle a user command. Normally the command is generated when the user +// makes a menu selection, but the command could really come from anywhere +// (for example, a toolbar with icon buttons, or from the dialog with the +// New, Open, Download, and Quit pushbuttons in it). +// +// This method examines the command, synchronizes with the CPU thread as +// necessary, executes the command, and catches any exceptions, showing them +// in an error dialog. +// +// This function is an EXCEPTION_CATCH_POINT. + +Bool EmDocument::HandleCommand (EmCommandID commandID) +{ + // Find information on how this command should be handled. + + size_t ii; + for (ii = 0; ii < countof (kCommand); ++ii) + { + if (kCommand[ii].fCommandID == commandID) + break; + } + + // If we couldn't find an entry for this command, assume that it's not + // a command for the document, and return false indicating that we did + // not handle the command. + + if (ii >= countof (kCommand)) + { + return false; // We did not handle this command. + } + + // Execute the command. Catch any exceptions and report them to the user. + + if (kCommand[ii].fFn) + { + try + { + (this->*(kCommand[ii].fFn)) (commandID); + } + catch (ErrCode errCode) + { + StrCode operation = kCommand[ii].fErrStrCode; + + Errors::ReportIfError (operation, errCode, 0, false); + } + } + + return true; // We handled this command. +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::HandleKey +// --------------------------------------------------------------------------- +// Handle the user pressing a key on their keyboard. + +void EmDocument::HandleKey (const EmKeyEvent& event) +{ + EmAssert (fSession); + + fSession->PostKeyEvent (event); +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::HandleButton +// --------------------------------------------------------------------------- +// Handle the user pressing on a skin button with their mouse. + +void EmDocument::HandleButton (SkinElementType theButton, Bool isDown) +{ + EmAssert (fSession); + + EmButtonEvent event (theButton, isDown); + fSession->PostButtonEvent (event); +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::HandleIdle +// --------------------------------------------------------------------------- +// Perform any document-level idle time operations. + +void EmDocument::HandleIdle (void) +{ + // Idle our sockets. + + CSocket::IdleAll (); + + // Idle any packets that are looking for signals. + // That is, see if any have timed out by now. + + RPC::Idle (); + + // If we need to start a new Gremlin Horde, and the OS + // is now booted enough to handle our mucking about as + // we start it up, then start starting it up. + + if (EmPatchState::EvtGetEventCalled ()) + { + HordeInfo info; + if (Startup::NewHorde (&info)) + { + this->ScheduleNewHorde (info); + } + } + + // Pop off deferred actions and handle them. + + this->DoAll (); +} + + +#pragma mark - + +// --------------------------------------------------------------------------- +// ¥ EmDocument::HandleSave +// --------------------------------------------------------------------------- +// Perform a standard Save operation. If the document hasn't been saved +// before, perform a "Save As" operation. Return whether or not the user +// cancelled the operation. On failure, an exception is thrown. + +Bool EmDocument::HandleSave (void) +{ + if (!fFile.IsSpecified ()) + { + return this->HandleSaveAs (); + } + + return this->HandleSaveTo (fFile); +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::HandleSaveAs +// --------------------------------------------------------------------------- +// Perform a standard Save As operation, asking the user for a file name. +// Return whether or not the user cancelled the operation. On failure, +// an exception is thrown. + +Bool EmDocument::HandleSaveAs (void) +{ + EmFileRef destRef; + + // Ask the user for a file to which to save the file. + + if (this->AskSaveSession (destRef)) + { + // If they did not cancel, save the file. + + return this->HandleSaveTo (destRef); + } + + // Return that we did not save the file. + + return false; +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::HandleSaveTo +// --------------------------------------------------------------------------- +// Perform a save operation to the given file. The given file may or may not +// already exist, but it must at least be specified. The user will NOT be +// asked for a file name. On success, the "last session" preference and the +// session MRU preference will be updated and this function will return true. +// On failure, an exception is thrown. +// +// This is the bottleneck routine for all document saving. Note that this +// is different from "session saving", which is a lower-level operation that +// can occur while Gremlins is running. + +Bool EmDocument::HandleSaveTo (const EmFileRef& destRef) +{ + EmAssert (destRef.IsSpecified ()); + + // Suspend the session so that we can save its data. + + EmSessionStopper stopper (fSession, kStopNow); + + // Have the session save itself. + + const Bool kUpdateFileRef = true; + fSession->Save (destRef, kUpdateFileRef); + + // Remember that we are now associated with this file. + + fFile = destRef; + + // Save the last-saved session file for next time. + + Preference<EmFileRef> pref (kPrefKeyLastPSF); + pref = destRef; + + // Update the MRU menu. + + gEmuPrefs->UpdateRAMMRU (destRef); + + // Return that we saved the file. + + return true; +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::HandleClose +// --------------------------------------------------------------------------- +// Handle a request to close the document. Get the user's preference with +// regards to saving the document before it's closed, and then call the +// version of HandleClose that takes the CloseActionType parameter. +// +// NOTE: this method can "delete this", so be careful not to access it after +// this method returns TRUE. + +Bool EmDocument::HandleClose (Bool quitting) +{ + Preference<CloseActionType> pref (kPrefKeyCloseAction); + return this->HandleClose (*pref, quitting); +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::HandleClose +// --------------------------------------------------------------------------- +// Handle a request to close the document. First, determine whether or not +// to save the document, based either on preference or on querying the user. +// Second, try to save the document if that's required. Third, if the +// document was saved or the user didn't cancel the save operation, close +// the document by deleting it. Finally, return whether or not the document +// was closed. +// +// NOTE: this method can "delete this", so be careful not to access it after +// this method returns TRUE. + +Bool EmDocument::HandleClose (CloseActionType closeAction, Bool quitting) +{ + EmDlgItemID answer; + + // If we have to ask, then ask. + + if (closeAction == kSaveAsk) + { + answer = this->AskSaveChanges (quitting); + } + + // If we always save, then pretend we asked and the user said yes. + + else if (closeAction == kSaveAlways) + { + answer = kDlgItemYes; + } + + // If we never save, then pretend we asked and the user said no. + + else // if (closeAction == kSaveNever) + { + answer = kDlgItemNo; + } + + EmAssert (answer == kDlgItemYes || answer == kDlgItemNo || answer == kDlgItemCancel); + + Bool closeIt = true; + + // If we want to save the document, then save it. If the save + // succeeds, then set the flag to also close the document. + + if (answer == kDlgItemYes) + { + closeIt = this->HandleSave (); + } + + // We don't want to save the document, and we no longer want + // to close it, either. + + else if (answer == kDlgItemCancel) + { + closeIt = false; + } + + // We didn't want to save the document, but we want to close + // it anyway. + + else // answer == kDlgItemNo + { + closeIt = true; + } + + // Close the document by deleting it. + + if (closeIt) + { + delete this; + } + + // Return whether or not we closed the document. It may or may not + // have been saved -- we're not saying which way with this response. + + return closeIt; +} + + +#pragma mark - + +// --------------------------------------------------------------------------- +// ¥ EmDocument::ScheduleNewHorde +// --------------------------------------------------------------------------- + +void EmDocument::ScheduleNewHorde (const HordeInfo& info) +{ + this->PostAction (new EmActionNewHorde (info)); +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::ScheduleDialog +// --------------------------------------------------------------------------- + +void EmDocument::ScheduleDialog (EmDlgThreadFn fn, + const void* parms, + EmDlgItemID& result) +{ + this->PostAction (new EmActionDialog (fn, parms, result)); +} + + +#pragma mark - + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoSave +// --------------------------------------------------------------------------- +// Handle the Save menu item. + +void EmDocument::DoSave (EmCommandID) +{ + this->HandleSave (); +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoSaveAs +// --------------------------------------------------------------------------- +// Handle the Save As menu item. + +void EmDocument::DoSaveAs (EmCommandID) +{ + this->HandleSaveAs (); +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoSaveBound +// --------------------------------------------------------------------------- +// Handle the Save Bound menu item. + +void EmDocument::DoSaveBound (EmCommandID) +{ + if (this->HostCanSaveBound ()) + { + EmDlg::DoSaveBound (); + } +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoSaveScreen +// --------------------------------------------------------------------------- +// Handle the Save Screen menu item. + +void EmDocument::DoSaveScreen (EmCommandID) +{ + EmFileRef destRef; + if (this->AskSaveScreen (destRef)) + { + this->HostSaveScreen (destRef); + } +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoInfo +// --------------------------------------------------------------------------- +// Handle the Session Info menu item. + +void EmDocument::DoInfo (EmCommandID) +{ + EmDlg::DoSessionInfo (); +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoImport +// --------------------------------------------------------------------------- +// Handle the Install Application/Database menu items. We handle all menu +// items in the sub-menu here. + +void EmDocument::DoImport (EmCommandID commandID) +{ + EmFileRefList fileList; + + // Ask the user for files to install. + + if (commandID == kCommandImportOther) + { + // If, when asking the user for a file to install, they press + // cancel, then just return right now. + + if (!this->AskImportFiles (fileList)) + { + return; + } + } + + // Get a file to install from the MRU list. + + else + { + int index = commandID - kCommandImport0; + EmFileRef importRef = gEmuPrefs->GetIndPRCMRU (index); + + // If, for some reason, the returned file reference is not + // specified, then just silently return right now. If the + // file doesn't exist, we'll let DoDatabaseImport report it + // or throw an exception. + + if (!importRef.IsSpecified ()) + { + return; + } + + // Put file in list. + + fileList.push_back (importRef); + } + + // Call the EmDlg routine that installs the file in tune with a + // progress dialog. + + EmDlg::DoDatabaseImport (fileList, kMethodBest); +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoExport +// --------------------------------------------------------------------------- +// Handle the Export Database menu item. + +void EmDocument::DoExport (EmCommandID) +{ + EmSessionStopper stopper (fSession, kStopOnSysCall); + EmDlg::DoDatabaseExport (); +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoHotSync +// --------------------------------------------------------------------------- +// Handle the HotSync menu item by simulating a press on the cradle button. + +void EmDocument::DoHotSync (EmCommandID) +{ + this->HandleButton (kElement_CradleButton, true); + this->HandleButton (kElement_CradleButton, false); +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoReset +// --------------------------------------------------------------------------- +// Handle the Reset menu item. + +void EmDocument::DoReset (EmCommandID) +{ + EmResetType type; + + if (EmDlg::DoReset (type) == kDlgItemOK) + { + EmSessionStopper stopper (fSession, kStopNow); + fSession->Reset (type); + } +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoGremlinNew +// --------------------------------------------------------------------------- +// Handle the New Gremlin menu item. + +void EmDocument::DoGremlinNew (EmCommandID) +{ + EmSessionStopper stopper (fSession, kStopOnSysCall); + EmDlg::DoHordeNew (); +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoGremlinSuspend +// --------------------------------------------------------------------------- +// Handle the Suspend Gremlin menu item. + +void EmDocument::DoGremlinSuspend (EmCommandID) +{ + EmSessionStopper stopper (fSession, kStopOnSysCall); + Hordes::Suspend (); +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoGremlinStep +// --------------------------------------------------------------------------- +// Handle the Step Gremlin menu item. + +void EmDocument::DoGremlinStep (EmCommandID) +{ + EmSessionStopper stopper (fSession, kStopOnSysCall); + Hordes::Step (); +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoGremlinResume +// --------------------------------------------------------------------------- +// Handle the Resume Gremlin menu item. + +void EmDocument::DoGremlinResume (EmCommandID) +{ + EmSessionStopper stopper (fSession, kStopOnSysCall); + Hordes::Resume (); +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoGremlinStop +// --------------------------------------------------------------------------- +// Handle the Stop Gremlin menu item. + +void EmDocument::DoGremlinStop (EmCommandID) +{ + EmSessionStopper stopper (fSession, kStopNow); + Hordes::Stop (); +} + + +#if HAS_PROFILING +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoProfileStart +// --------------------------------------------------------------------------- +// Handle the Start Profile menu item. + +void EmDocument::DoProfileStart (EmCommandID) +{ + EmSessionStopper stopper (fSession, kStopNow); + ::ProfileStart (); +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoProfileStop +// --------------------------------------------------------------------------- +// Handle the Stop Profile menu item. + +void EmDocument::DoProfileStop (EmCommandID) +{ + EmSessionStopper stopper (fSession, kStopNow); + ::ProfileStop (); +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::DoProfileDump +// --------------------------------------------------------------------------- +// Handle the Dump Profile menu item. + +void EmDocument::DoProfileDump (EmCommandID) +{ + EmSessionStopper stopper (fSession, kStopNow); + ::ProfileDump (NULL); +} +#endif + + +#pragma mark - + +// --------------------------------------------------------------------------- +// ¥ EmDocument::AskNewSession +// --------------------------------------------------------------------------- +// Ask the user for new session configuration information. If the user +// cancels, return false. Otherwise, return true and store the new +// configuration information in cfg. The cfg parameter is also used to +// provide the initial settings in the dialog box. + +Bool EmDocument::AskNewSession (Configuration& cfg) +{ + EmAssert (!gApplication->IsBound ()); + + // Ask the user for new configuration information. + + EmDlgItemID item = EmDlg::DoSessionNew (cfg); + + // Return whether or not the user cancelled the operation. + + return item == kDlgItemOK; +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::AskSaveSession +// --------------------------------------------------------------------------- +// Ask the user for a file to which to save the document. If the user +// cancels, return false. Otherwise, return true and store the specified +// file name in "ref". The ref parameter also provides a default file name +// if it is specified. + +Bool EmDocument::AskSaveSession (EmFileRef& ref) +{ + // Start by showing the user the directory in which they saved the + // last session file. + + Preference<EmFileRef> pref (kPrefKeyLastPSF); + EmFileRef lastSession = *pref; + + // Get other parameters used in presenting the dialog. + + string prompt (Platform::GetString (kStr_SaveSessionAs)); + EmDirRef defaultPath (lastSession.GetParent ()); + EmFileTypeList filterList; + string defaultName (ref.GetName ()); + + filterList.push_back (kFileTypeSession); + filterList.push_back (kFileTypeAll); + + // Ask the user for a file name. + + EmDlgItemID item = EmDlg::DoPutFile ( + ref, prompt, defaultPath, filterList, defaultName); + + // Return whether or not the user cancelled the operation. + + return item == kDlgItemOK; +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::AskLoadSession +// --------------------------------------------------------------------------- +// Ask the user for a session document to load. If the user cancels, return +// false. Otherwise, return true and store the specified file name in "ref". +// The ref parameter also provides a default file name if it is specified. + +Bool EmDocument::AskLoadSession (EmFileRef& ref, EmFileType type) +{ + EmAssert (!gApplication->IsBoundFully ()); + + // Start by showing the user the directory in which they saved the + // last session file. + + Preference<EmFileRef> pref (kPrefKeyLastPSF); + EmFileRef lastSession = *pref; + + // Get other parameters used in presenting the dialog. + + string prompt (Platform::GetString (kStr_LoadSession)); + EmDirRef defaultPath (lastSession.GetParent ()); + EmFileTypeList filterList; + + filterList.push_back (type); + filterList.push_back (kFileTypeAll); + + // Ask the user for a file name. + + EmDlgItemID item = EmDlg::DoGetFile ( + ref, prompt, defaultPath, filterList); + + // Return whether or not the user cancelled the operation. + + return item == kDlgItemOK; +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::AskSaveChanges +// --------------------------------------------------------------------------- +// Ask the user if they want to save their changes to the session document. +// If the document had been saved before, ask the user if they want to save +// changes to the document with that name. Otherwise, ask them if they want +// to save the "Untitled" document. Also, ask them if they'd like to save +// the changes before "closing" or before "quitting". Return the user's +// choice from the dialog: Yes, No, or Cancel. + +EmDlgItemID EmDocument::AskSaveChanges (Bool quitting) +{ + string name; + + if (fFile.IsSpecified ()) + { + name = fFile.GetName (); + } + else + { + // DoSessionSave provides the kStr_Untitled string + // if the given string is empty. + } + + EmDlgItemID item = EmDlg::DoSessionSave (name, quitting); + + EmAssert (item == kDlgItemYes || item == kDlgItemNo || item == kDlgItemCancel); + + return item; +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::AskSaveScreen +// --------------------------------------------------------------------------- +// Ask the user for a file to which they want to save the screen contents. If +// the user cancels, return false. Otherwise, return true and store the +// specified file name in "ref". The ref parameter also provides a default +// file name if it is specified. + +Bool EmDocument::AskSaveScreen (EmFileRef& ref) +{ + // !!! Need to preserve the last directory to which a picture was + // saved so that we can restore it here. + + // Get other parameters used in presenting the dialog. + + string prompt (Platform::GetString (kStr_SaveScreenAs)); + EmDirRef defaultPath; + EmFileTypeList filterList; + string defaultName; + + filterList.push_back (kFileTypePicture); + filterList.push_back (kFileTypeAll); + + // Ask the user for a file name. + + EmDlgItemID item = EmDlg::DoPutFile ( + ref, prompt, defaultPath, filterList, defaultName); + + // Return whether or not the user cancelled the operation. + + return item == kDlgItemOK; +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::AskImportFiles +// --------------------------------------------------------------------------- +// Ask the user for files they want to import. If the user cancels, return +// false. Otherwise, return true and store the specified file names in +// "listRef". + +Bool EmDocument::AskImportFiles (EmFileRefList& listRef) +{ + // Get other parameters used in presenting the dialog. + + string prompt (Platform::GetString (kStr_ImportFile)); + EmDirRef defaultPath; + EmFileTypeList filterList; + + filterList.push_back (kFileTypePalmApp); + filterList.push_back (kFileTypePalmDB); + filterList.push_back (kFileTypePalmQA); + + // Start by showing the user the directory from which they + // last loaded a PRC/PDB/PQA file. + + EmFileRef lastImport = gEmuPrefs->GetIndPRCMRU (0); + if (lastImport.IsSpecified ()) + { + defaultPath = lastImport.GetParent (); + } + + // Ask the user for file names. + + EmDlgItemID item = EmDlg::DoGetFileList ( + listRef, prompt, defaultPath, filterList); + + // Return whether or not the user cancelled the operation. + + return item == kDlgItemOK; +} + + +#pragma mark - + +// --------------------------------------------------------------------------- +// ¥ EmDocument::HostCanSaveBound +// --------------------------------------------------------------------------- + +Bool EmDocument::HostCanSaveBound (void) +{ + return false; +} + + +// --------------------------------------------------------------------------- +// ¥ EmDocument::HostSaveScreen +// --------------------------------------------------------------------------- + +void EmDocument::HostSaveScreen (const EmFileRef&) +{ +} + + +#pragma mark - + +// --------------------------------------------------------------------------- +// ¥ EmDocument::PrvOpenWindow +// --------------------------------------------------------------------------- +// Create the window for a new document. + +void EmDocument::PrvOpenWindow (void) +{ + if (gWindow == NULL) + { + EmWindow::NewWindow (); + } + else + { + // If the window is already open, then at least reset it so that + // it can get its new skin. + + gWindow->WindowReset (); + } +} |