Bug #20232, r=scc@netscape.com git-svn-id: svn://10.0.0.236/trunk@57423 18797224-902f-48f8-a5cc-f745e15eee43
1275 lines
57 KiB
C++
1275 lines
57 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||
*
|
||
* The contents of this file are subject to the Netscape Public
|
||
* License Version 1.1 (the "License"); you may not use this file
|
||
* except in compliance with the License. You may obtain a copy of
|
||
* the License at http://www.mozilla.org/NPL/
|
||
*
|
||
* Software distributed under the License is distributed on an "AS
|
||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||
* implied. See the License for the specific language governing
|
||
* rights and limitations under the License.
|
||
*
|
||
* The Original Code is Mozilla Communicator client code.
|
||
*
|
||
* The Initial Developer of the Original Code is Netscape Communications
|
||
* Corporation. Portions created by Netscape are
|
||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||
* Rights Reserved.
|
||
*
|
||
* Contributor(s):
|
||
* Pierre Phaneuf <pp@ludusdesign.com>
|
||
*/
|
||
|
||
// Special stuff for the Macintosh implementation of command-line service.
|
||
|
||
#include "nsCommandLineServiceMac.h"
|
||
|
||
// Mozilla
|
||
#include "nsFileSpec.h"
|
||
#include "nsFileStream.h"
|
||
#include "nsAppleEvents.h"
|
||
#include "nsDebug.h"
|
||
#include "nsIAppShellService.h"
|
||
#include "nsIServiceManager.h"
|
||
#include "nsIURL.h"
|
||
#include "nsIIOService.h"
|
||
#include "nsIURL.h"
|
||
#include "nsIServiceManager.h"
|
||
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
||
#include "nsIBrowserWindow.h"
|
||
#include "nsIWebShellWindow.h"
|
||
#include "nsIWebShell.h"
|
||
#include "nsIDOMWindow.h"
|
||
#include "jsapi.h"
|
||
|
||
// NSPR
|
||
#include "prmem.h"
|
||
#include "plstr.h"
|
||
#include "prenv.h"
|
||
#include "prlog.h"
|
||
|
||
// Universal
|
||
#include <AppleEvents.h>
|
||
#include <AEObjects.h>
|
||
#include <AERegistry.h>
|
||
#include <Processes.h>
|
||
#include <Displays.h> // For the display notice event
|
||
#include <Balloons.h>
|
||
#include <Errors.h>
|
||
#include <EPPC.h>
|
||
|
||
// PowerPlant
|
||
#include <UAppleEventsMgr.h>
|
||
#include <UExtractFromAEDesc.h>
|
||
|
||
#include "nsAppShellCIDs.h"
|
||
static NS_DEFINE_IID(kAppShellServiceCID, NS_APPSHELL_SERVICE_CID);
|
||
|
||
// Global buffers for command-line arguments and parsing.
|
||
#define MAX_BUF 512
|
||
#define MAX_TOKENS 20
|
||
static char* argBuffer = nsnull; // the command line itself
|
||
static char** args = nsnull; // array of pointers into argBuffer
|
||
|
||
static nsIWebShellWindow* FindWebShellWindow(nsIXULWindowCallbacks* cb);
|
||
|
||
//========================================================================================
|
||
class nsAppleEventHandler
|
||
//========================================================================================
|
||
{
|
||
|
||
|
||
public:
|
||
enum KioskEnum
|
||
{
|
||
KioskOff = 0
|
||
, KioskOn = 1
|
||
};
|
||
|
||
nsAppleEventHandler();
|
||
virtual ~nsAppleEventHandler();
|
||
|
||
static nsAppleEventHandler* Get()
|
||
{
|
||
if (!sAppleEventHandler)
|
||
new nsAppleEventHandler();
|
||
return sAppleEventHandler;
|
||
}
|
||
|
||
void SetStartedUp(PRBool inStarted) { mStartedUp = inStarted; }
|
||
|
||
// --- Top Level Apple Event Handling
|
||
|
||
virtual OSErr HandleAppleEvent(const AppleEvent &inAppleEvent,
|
||
AppleEvent &outAEReply,
|
||
AEDesc &outResult,
|
||
SInt32 inAENumber);
|
||
virtual OSErr GetAEProperty(DescType inProperty,
|
||
const AEDesc &inRequestedType,
|
||
AEDesc &outPropertyDesc) const;
|
||
virtual OSErr SetAEProperty(DescType inProperty,
|
||
const AEDesc &inRequestedType,
|
||
AEDesc &outPropertyDesc);
|
||
|
||
// --- AEOM support
|
||
OSErr GetSubModelByUniqueID(DescType inModelID,
|
||
const AEDesc &inKeyData,
|
||
AEDesc &outToken) const;
|
||
|
||
static KioskEnum GetKioskMode(){return sAppleEventHandler->mKioskMode;}
|
||
|
||
private:
|
||
|
||
|
||
OSErr HandleAEOpenOrPrintDoc(
|
||
const AppleEvent &inAppleEvent,
|
||
AppleEvent& outAEReply,
|
||
SInt32 inAENumber);
|
||
|
||
OSErr HandleOpen1Doc(const FSSpec& inFileSpec,
|
||
OSType fileType);
|
||
|
||
OSErr HandlePrint1Doc(const FSSpec& inFileSpec,
|
||
OSType fileType);
|
||
|
||
PRBool EnsureCommandLine();
|
||
|
||
OSErr AddToCommandLine(const char* inArgText);
|
||
|
||
OSErr AddToCommandLine(const char* inOptionString,
|
||
const FSSpec& inFileSpec);
|
||
|
||
void AddToEnvironmentVars(const char* inArgText);
|
||
|
||
OSErr DispatchURLToNewBrowser(const char* url);
|
||
|
||
OSErr HandleOpenURLEvent(const AppleEvent &inAppleEvent,
|
||
AppleEvent &outAEReply,
|
||
AEDesc &outResult,
|
||
SInt32 inAENumber);
|
||
// spy Apple Event suite
|
||
// file/URL opening + misc
|
||
OSErr HandleGetURLEvent(const AppleEvent &inAppleEvent,
|
||
AppleEvent &outAEReply,
|
||
AEDesc &outResult,
|
||
SInt32 inAENumber);
|
||
|
||
// Netscape suite
|
||
OSErr HandleDoJavascriptEvent(const AppleEvent &inAppleEvent,
|
||
AppleEvent &outAEReply,
|
||
AEDesc &outResult,
|
||
SInt32 inAENumber);
|
||
|
||
static pascal OSErr AppleEventHandler(
|
||
const AppleEvent* inAppleEvent,
|
||
AppleEvent* outAEReply,
|
||
UInt32 inRefCon);
|
||
|
||
protected:
|
||
KioskEnum mKioskMode;
|
||
PRBool mStartedUp;
|
||
static nsAppleEventHandler* sAppleEventHandler; // One and only instance of AEvents
|
||
|
||
}; // class nsAppleEventHandler
|
||
|
||
//========================================================================================
|
||
class MoreExtractFromAEDesc
|
||
// Apple event helpers -- extension of UExtractFromAEDesc.h
|
||
// All the miscellaneous AppleEvent helper routines.
|
||
//========================================================================================
|
||
{
|
||
public:
|
||
|
||
// --------------------------------------------------------------
|
||
/* Given an AppleEvent, locate a string given a keyword and
|
||
return the string
|
||
In: Event to search
|
||
AEKeyword assocaated with the string
|
||
C string ptr
|
||
Out: Pointer to a newly created C string returned */
|
||
// --------------------------------------------------------------
|
||
static void GetCString(const AppleEvent &inAppleEvent, AEKeyword keyword,
|
||
char * & s, Boolean inThrowIfError = true);
|
||
|
||
// --------------------------------------------------------------
|
||
/* Given an AEDesc of type typeChar, return it's string.
|
||
In: AEDesc containing a string
|
||
C string ptr
|
||
Out: Pointer to a newly created C string returned */
|
||
// --------------------------------------------------------------
|
||
static void TheCString(const AEDesc &inDesc, char * & outPtr);
|
||
|
||
// --------------------------------------------------------------
|
||
/* Add an error string and error code to an AppleEvent.
|
||
Typically used when constructing the return event when an
|
||
error occured
|
||
In: Apple Event to append to
|
||
Error string
|
||
Error code
|
||
Out: keyErrorNum and keyErrorSting AEDescs are added to the Event. */
|
||
// --------------------------------------------------------------
|
||
static void MakeErrorReturn(AppleEvent &event, ConstStr255Param errorString,
|
||
OSErr errorCode);
|
||
|
||
// --------------------------------------------------------------
|
||
/* Display an error dialog if the given AppleEvent contains
|
||
a keyErrorNumber. a keyErrorString is optional and will be
|
||
displayed if present
|
||
In: Apple Event
|
||
Out: Error dialog displayed if error data present. */
|
||
// --------------------------------------------------------------
|
||
static Boolean DisplayErrorReply(AppleEvent &reply);
|
||
|
||
// --------------------------------------------------------------
|
||
/* Return the process serial number of the sending process.
|
||
In: Apple Event send by some app.
|
||
Out: ProcessSerialNumber of the sending app. */
|
||
// --------------------------------------------------------------
|
||
static ProcessSerialNumber ExtractAESender(const AppleEvent &inAppleEvent);
|
||
|
||
static void DispatchURLDirectly(const AppleEvent &inAppleEvent);
|
||
}; // class MoreExtractFromAEDesc
|
||
|
||
|
||
//========================================================================================
|
||
class AEUtilities
|
||
// Some more simple Apple Event utility routines.
|
||
//========================================================================================
|
||
{
|
||
public:
|
||
|
||
// --------------------------------------------------------------
|
||
/* CreateAppleEvent
|
||
Create a new Apple Event from scratch.
|
||
In: Apple Event suite
|
||
Apple Event ID
|
||
Ptr to return Apple Event
|
||
ProcessSerialNumber of the target app to send event to.
|
||
Out:A new Apple Event is created. More data may be added to
|
||
the event simply by calling AEPutParamDesc or AEPutParamPtr */
|
||
// --------------------------------------------------------------
|
||
static OSErr CreateAppleEvent(OSType suite, OSType id,
|
||
AppleEvent &event, ProcessSerialNumber targetPSN);
|
||
|
||
// --------------------------------------------------------------
|
||
/* Check to see if there is an error in the given AEvent.
|
||
We simply return an OSError equiv to the error value
|
||
in the event. If none exists (or an error took place
|
||
during access) we return 0.
|
||
In: Apple Event to test
|
||
Out:Error value returned */
|
||
// --------------------------------------------------------------
|
||
static OSErr EventHasErrorReply(AppleEvent & reply);
|
||
|
||
}; // AEUtilities
|
||
|
||
//========================================================================================
|
||
// Implementation of nsAppleEventHandler
|
||
//========================================================================================
|
||
|
||
#pragma mark -
|
||
|
||
nsAppleEventHandler* nsAppleEventHandler::sAppleEventHandler = nsnull;
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
nsAppleEventHandler::nsAppleEventHandler()
|
||
//----------------------------------------------------------------------------------------
|
||
: mKioskMode(KioskOff) // We assume not operating in kiosk mode unless told otherwise
|
||
, mStartedUp(PR_FALSE)
|
||
{
|
||
// We're a singleton class
|
||
sAppleEventHandler = this;
|
||
|
||
// We must not throw out of here.
|
||
try
|
||
{
|
||
UAppleEventsMgr::InstallAEHandlers(
|
||
NewAEEventHandlerProc(nsAppleEventHandler::AppleEventHandler));
|
||
}
|
||
catch(...)
|
||
{
|
||
}
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
nsAppleEventHandler::~nsAppleEventHandler()
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
// We're a singleton class
|
||
sAppleEventHandler = nsnull;
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
pascal OSErr nsAppleEventHandler::AppleEventHandler(
|
||
const AppleEvent* inAppleEvent,
|
||
AppleEvent* outAEReply,
|
||
UInt32 inRefCon)
|
||
// This is the function that gets installed as the AE callback.
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
OSErr err = noErr;
|
||
// We must not throw out of here.
|
||
try
|
||
{
|
||
StAEDescriptor resultDesc;
|
||
err = sAppleEventHandler->HandleAppleEvent(
|
||
*inAppleEvent, *outAEReply, resultDesc, inRefCon);
|
||
}
|
||
catch(...)
|
||
{
|
||
err = errAEEventNotHandled;
|
||
}
|
||
return err;
|
||
} // nsAppleEventHandler::AppleEventHandler
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
OSErr nsAppleEventHandler::HandleAppleEvent(
|
||
const AppleEvent &inAppleEvent,
|
||
AppleEvent &outAEReply,
|
||
AEDesc &outResult,
|
||
SInt32 inAENumber)
|
||
// nsAppleEventHandler::HandleAppleEvent
|
||
// AppleEvent Dispach Here
|
||
// In: & AppleEvent Incoming apple event
|
||
// & ReplyEvent Reply event we can attach result info to
|
||
// & Descriptor OUtgoing descriptor
|
||
// AppleEvent ID The Apple Event ID we were called with.
|
||
// Out: Event Handled by CAppleEvent
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
OSErr err = errAEEventNotHandled;
|
||
switch (inAENumber)
|
||
{
|
||
case AE_GetURL:
|
||
case AE_OpenURL:
|
||
case ae_OpenApp:
|
||
case ae_OpenDoc:
|
||
case ae_PrintDoc:
|
||
case ae_Quit:
|
||
break;
|
||
|
||
default:
|
||
// Ignore all apple events handled by this handler except get url, open
|
||
// url and the required suite until we have properly started up.
|
||
if (!mStartedUp)
|
||
return errAEEventNotHandled;
|
||
break;
|
||
}
|
||
|
||
switch (inAENumber)
|
||
{
|
||
|
||
case ae_OpenApp:
|
||
err = noErr;
|
||
break;
|
||
|
||
case ae_Quit:
|
||
{
|
||
nsresult rv;
|
||
NS_WITH_SERVICE(nsIAppShellService, appShellService, kAppShellServiceCID, &rv);
|
||
if (NS_FAILED(rv))
|
||
return errAEEventNotHandled;
|
||
appShellService->Quit();
|
||
break;
|
||
}
|
||
case ae_OpenDoc:
|
||
case ae_PrintDoc:
|
||
err = HandleAEOpenOrPrintDoc(inAppleEvent, outAEReply, inAENumber);
|
||
break;
|
||
|
||
// ### Mac URL standard Suite
|
||
// -----------------------------------------------------------
|
||
case AE_GetURL: // Direct object - url, cwin - HyperWindow
|
||
err = HandleGetURLEvent( inAppleEvent, outAEReply, outResult, inAENumber );
|
||
break;
|
||
|
||
// ### Spyglass Suite
|
||
// -----------------------------------------------------------
|
||
case AE_OpenURL:
|
||
err = HandleOpenURLEvent( inAppleEvent, outAEReply, outResult, inAENumber );
|
||
break;
|
||
|
||
|
||
// ### Netscape Experimental Suite
|
||
// -----------------------------------------------------------
|
||
case AE_DoJavascript:
|
||
err = HandleDoJavascriptEvent( inAppleEvent, outAEReply, outResult, inAENumber );
|
||
break;
|
||
|
||
// ### If all else fails behave like a word processor
|
||
// -----------------------------------------------------------
|
||
default:
|
||
NS_NOTYETIMPLEMENTED("Write Me");
|
||
//CFrontApp::sApplication->LDocApplication::HandleAppleEvent( inAppleEvent, outAEReply, outResult, inAENumber );
|
||
break;
|
||
}
|
||
return noErr;
|
||
} // nsAppleEventHandler::HandleAppleEvent
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
OSErr nsAppleEventHandler::HandleAEOpenOrPrintDoc(
|
||
const AppleEvent &inAppleEvent,
|
||
AppleEvent& /* outAEReply */,
|
||
SInt32 inAENumber)
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
AEDescList docList;
|
||
OSErr err = ::AEGetParamDesc(&inAppleEvent, keyDirectObject,
|
||
typeAEList, &docList);
|
||
if (err) return err;
|
||
|
||
SInt32 numDocs;
|
||
err = ::AECountItems(&docList, &numDocs);
|
||
if (err)
|
||
goto Clean;
|
||
|
||
// Loop through all items in the list
|
||
// Extract descriptor for the document
|
||
// Coerce descriptor data into a FSSpec
|
||
// Dispatch the print or open to the appropriate routine
|
||
for (int i = 1; i <= numDocs; i++)
|
||
{
|
||
AEKeyword keyWord;
|
||
DescType descType;
|
||
FSSpec spec;
|
||
Size theSize;
|
||
err = ::AEGetNthPtr(&docList, i, typeFSS, &keyWord, &descType,
|
||
(Ptr) &spec, sizeof(FSSpec), &theSize);
|
||
if (err)
|
||
goto Clean;
|
||
|
||
nsFileSpec nsspec(spec);
|
||
CInfoPBRec info;
|
||
nsspec.GetCatInfo(info);
|
||
OSType fileType = info.hFileInfo.ioFlFndrInfo.fdType;
|
||
if (inAENumber == ae_OpenDoc)
|
||
err = HandleOpen1Doc(spec, fileType);
|
||
else
|
||
err = HandlePrint1Doc(spec, fileType);
|
||
}
|
||
Clean:
|
||
::AEDisposeDesc(&docList);
|
||
return err;
|
||
} // nsAppleEventHandler::HandleAEOpenOrPrintDoc
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
PRBool nsAppleEventHandler::EnsureCommandLine()
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
if (argBuffer)
|
||
return PR_TRUE;
|
||
argBuffer = new char[MAX_BUF];
|
||
if (!argBuffer)
|
||
return PR_FALSE;
|
||
PL_strcpy(argBuffer, "mozilla"); // argv[0]
|
||
return PR_TRUE;
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
OSErr nsAppleEventHandler::AddToCommandLine(const char* inOptionString, const FSSpec& inFileSpec)
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
// Convert the filespec to a URL
|
||
nsFileSpec nsspec(inFileSpec);
|
||
nsFileURL fileAsURL(nsspec);
|
||
PL_strcat(argBuffer, " ");
|
||
AddToCommandLine(inOptionString);
|
||
AddToCommandLine(fileAsURL.GetAsString());
|
||
return noErr;
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
OSErr nsAppleEventHandler::AddToCommandLine(const char* inArgText)
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
if (!EnsureCommandLine())
|
||
return memFullErr;
|
||
if (*inArgText != ' ')
|
||
PL_strcat(argBuffer, " ");
|
||
PL_strcat(argBuffer, inArgText);
|
||
return noErr;
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
void nsAppleEventHandler::AddToEnvironmentVars(const char* inArgText)
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
(void)PR_PutEnv(inArgText);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
static nsresult openWindow( const char *chrome, const PRUnichar *url )
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
nsresult rv;
|
||
NS_WITH_SERVICE(nsIAppShellService, appShellService, kAppShellServiceCID, &rv)
|
||
if (NS_SUCCEEDED(rv))
|
||
{
|
||
nsCOMPtr<nsIDOMWindow> hiddenWindow;
|
||
JSContext *jsContext;
|
||
rv = appShellService->GetHiddenWindowAndJSContext( getter_AddRefs( hiddenWindow ),
|
||
&jsContext );
|
||
if (NS_SUCCEEDED(rv))
|
||
{
|
||
void *stackPtr;
|
||
jsval *argv = JS_PushArguments( jsContext,
|
||
&stackPtr,
|
||
"sssW",
|
||
chrome,
|
||
"_blank",
|
||
"chrome,dialog=no,all",
|
||
url );
|
||
if(argv)
|
||
{
|
||
nsCOMPtr<nsIDOMWindow> newWindow;
|
||
rv = hiddenWindow->OpenDialog( jsContext,
|
||
argv,
|
||
4,
|
||
getter_AddRefs( newWindow ) );
|
||
JS_PopArguments( jsContext, stackPtr );
|
||
}
|
||
}
|
||
}
|
||
return rv;
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
OSErr nsAppleEventHandler::HandleOpen1Doc(const FSSpec& inFileSpec, OSType inFileType)
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
if (!mStartedUp)
|
||
{
|
||
// Is it the right type to be a command-line file?
|
||
if (inFileType == 'TEXT' || inFileType == 'CMDL')
|
||
{
|
||
// Can we open the file?
|
||
nsInputFileStream s(inFileSpec);
|
||
if (s.is_open())
|
||
{
|
||
Boolean foundArgs = false;
|
||
Boolean foundEnv = false;
|
||
char chars[1024];
|
||
const char* kCommandLinePrefix = "ARGS:";
|
||
const char* kEnvVarLinePrefix = "ENV:";
|
||
s.readline(chars, sizeof(chars));
|
||
|
||
do
|
||
{ // See if there are any command line or environment var settings
|
||
if (PL_strstr(chars, kCommandLinePrefix) == chars)
|
||
{
|
||
(void)AddToCommandLine(chars + PL_strlen(kCommandLinePrefix));
|
||
foundArgs = true;
|
||
}
|
||
else if (PL_strstr(chars, kEnvVarLinePrefix) == chars)
|
||
{
|
||
(void)AddToEnvironmentVars(chars + PL_strlen(kEnvVarLinePrefix));
|
||
foundEnv = true;
|
||
}
|
||
|
||
// Clear the buffer and get the next line from the command line file
|
||
chars[0] = '\0';
|
||
s.readline(chars, sizeof(chars));
|
||
} while (PL_strlen(chars));
|
||
|
||
// If we found any environment vars we need to re-init NSPR's logging
|
||
// so that it knows what the new vars are
|
||
if (foundEnv)
|
||
PR_Init_Log();
|
||
|
||
// If we found a command line or environment vars we want to return now
|
||
// raather than trying to open the file as a URL
|
||
if (foundArgs || foundEnv)
|
||
return noErr;
|
||
}
|
||
}
|
||
// If it's not a command-line argument, and we are starting up the application,
|
||
// add a command-line "-url" argument to the global list. This means that if
|
||
// the app is opened with documents on the mac, they'll be handled the same
|
||
// way as if they had been typed on the command line in Unix or DOS.
|
||
return AddToCommandLine("-url", inFileSpec);
|
||
}
|
||
// Final case: we're not just starting up. How do we handle this?
|
||
nsFileSpec fileSpec(inFileSpec);
|
||
nsFileURL fileURL(fileSpec);
|
||
nsString urlString(fileURL.GetURLString());
|
||
nsresult rv;
|
||
rv = openWindow( "chrome://navigator/content", urlString.GetUnicode() );
|
||
if (NS_FAILED(rv))
|
||
return errAEEventNotHandled;
|
||
return noErr;
|
||
} // nsAppleEventHandler::HandleOpen1Doc
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
OSErr nsAppleEventHandler::HandlePrint1Doc(const FSSpec& inFileSpec, OSType fileType)
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
// If we are starting up the application,
|
||
// add a command-line "-print" argument to the global list. This means that if
|
||
// the app is opened with documents on the mac, they'll be handled the same
|
||
// way as if they had been typed on the command line in Unix or DOS.
|
||
if (!mStartedUp)
|
||
return AddToCommandLine("-print", inFileSpec);
|
||
// Final case: we're not just starting up. How do we handle this?
|
||
NS_NOTYETIMPLEMENTED("Write Me");
|
||
return errAEEventNotHandled;
|
||
}
|
||
|
||
/*##########################################################################*/
|
||
/* ---- Mac URL standard, supported by many apps ---- */
|
||
/*##########################################################################*/
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
OSErr nsAppleEventHandler::DispatchURLToNewBrowser(const char* url)
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
OSErr err;
|
||
if (mStartedUp)
|
||
{
|
||
nsresult rv;
|
||
rv = openWindow( "chrome://navigator/content", nsString(url).GetUnicode() );
|
||
if (NS_FAILED(rv))
|
||
return errAEEventNotHandled;
|
||
}
|
||
else
|
||
err = AddToCommandLine(url);
|
||
return err;
|
||
} // nsAppleEventHandler::DispatchURLToNewBrowser
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
OSErr nsAppleEventHandler::HandleGetURLEvent(
|
||
const AppleEvent &inAppleEvent,
|
||
AppleEvent &outAEReply,
|
||
AEDesc& outResult,
|
||
SInt32 /*inAENumber*/)
|
||
// nsAppleEventHandler::HandleGetURLEvent Suite:URL
|
||
// Dispach the URL event to the correct window and let the
|
||
// window handle the event.
|
||
//
|
||
//GetURL: Loads the URL (optionaly to disk)
|
||
//
|
||
// GetURL string -- The url
|
||
// [to file specification] -- file the URL should be loaded into
|
||
// [inside reference] -- Window the URL should be loaded to
|
||
// [from string] -- Refererer, to be sent with the HTTP request
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
OSErr err = noErr;
|
||
char* url = nsnull;
|
||
MoreExtractFromAEDesc::GetCString(inAppleEvent, keyDirectObject, url);
|
||
if (!url)
|
||
return errAEParamMissed;
|
||
err = DispatchURLToNewBrowser(url);
|
||
PR_DELETE(url);
|
||
return err;
|
||
} // nsAppleEventHandler::HandleGetURLEvent
|
||
|
||
/*##########################################################################*/
|
||
/* ---- The Spyglass Suite ---- */
|
||
/*##########################################################################*/
|
||
|
||
#define errMakeNewWindow 100
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
OSErr nsAppleEventHandler::HandleOpenURLEvent(
|
||
const AppleEvent &inAppleEvent,
|
||
AppleEvent &outAEReply,
|
||
AEDesc& outResult,
|
||
SInt32 /*inAENumber*/)
|
||
// nsAppleEventHandler::HandleOpenURLEvent Suite:Spyglass
|
||
// Open to a URL
|
||
// In: Incoming apple event, reply event, outtgoing descriptor, eventID
|
||
//
|
||
// Flavors of OpenURL
|
||
// #define AE_spy_openURL 'OURL' // typeChar OpenURL
|
||
// AE_spy_openURL_into // typeFSS into
|
||
// AE_spy_openURL_wind // typeLongInteger windowID
|
||
// AE_spy_openURL_flag // typeLongInteger flags
|
||
// 4 bits used.
|
||
// 1 =
|
||
// 2 =
|
||
// 4 =
|
||
// 8 = Open into editor window
|
||
// AE_spy_openURL_post // typeWildCard post data
|
||
// AE_spy_openURL_mime // typeChar MIME type
|
||
// AE_spy_openURL_prog // typePSN Progress app
|
||
//
|
||
// Just like with GetURL, figure out the window, and let it handle the load
|
||
// Arguments we care about: AE_spy_openURL_wind
|
||
//
|
||
// Out: OpenURLEvent handled
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
OSErr err = noErr;
|
||
char* url = nsnull;
|
||
MoreExtractFromAEDesc::GetCString(inAppleEvent, keyDirectObject, url);
|
||
if (!url)
|
||
return errAEParamMissed;
|
||
err = DispatchURLToNewBrowser(url);
|
||
PR_DELETE(url);
|
||
return err;
|
||
} // nsAppleEventHandler::HandleOpenURLEvent
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
OSErr nsAppleEventHandler::HandleDoJavascriptEvent(
|
||
const AppleEvent& inAppleEvent,
|
||
AppleEvent& /*outAEReply*/,
|
||
AEDesc& /*outResult*/,
|
||
SInt32 /*inAENumber*/)
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
OSErr err = noErr;
|
||
// Get the direct object - the string to execute.
|
||
char *scriptText = nsnull;
|
||
MoreExtractFromAEDesc::GetCString(inAppleEvent, keyDirectObject, scriptText);
|
||
if (!scriptText)
|
||
return errAEParamMissed;
|
||
const char* kJavascriptPrefix = "javascript:";
|
||
char* url = (char*)PR_MALLOC(PL_strlen(scriptText) + PL_strlen(kJavascriptPrefix) + 2);
|
||
if (!url)
|
||
{
|
||
PR_FREEIF(scriptText);
|
||
return memFullErr;
|
||
}
|
||
PL_strcpy(url, kJavascriptPrefix);
|
||
PL_strcat(url, scriptText);
|
||
PR_FREEIF(scriptText);
|
||
err = DispatchURLToNewBrowser(url);
|
||
Clean:
|
||
PR_FREEIF(url);
|
||
return err;
|
||
}
|
||
|
||
/*##########################################################################*/
|
||
/* ---- Apple Event Object Model support ---- */
|
||
/*##########################################################################*/
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
OSErr nsAppleEventHandler::GetSubModelByUniqueID(DescType inModelID, const AEDesc &inKeyData, AEDesc &outToken) const
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
OSErr err = noErr;
|
||
NS_NOTYETIMPLEMENTED("Write Me");
|
||
#if 0
|
||
switch (inModelID)
|
||
{
|
||
case cWindow: // The hyperwindows have unique IDs that can be resolved
|
||
// FFFFFFFFF is the front window, 0 is a new window
|
||
Int32 windowID;
|
||
UExtractFromAEDesc::TheInt32(inKeyData, windowID);
|
||
LWindow* foundWindow = CBrowserWindow::GetWindowByID(windowID);
|
||
if (foundWindow == nsnull)
|
||
ThrowOSErr_(errAENoSuchObject);
|
||
else
|
||
{
|
||
NS_NOTYETIMPLEMENTED("Write Me");
|
||
// CFrontApp::sApplication->PutInToken(foundWindow, outToken);
|
||
}
|
||
break;
|
||
default:
|
||
NS_NOTYETIMPLEMENTED("Write Me");
|
||
// CFrontApp::sApplication->LDocApplication::GetSubModelByUniqueID(inModelID, inKeyData, outToken);
|
||
break;
|
||
}
|
||
#endif // 0
|
||
return err;
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
OSErr nsAppleEventHandler::GetAEProperty(DescType inProperty,
|
||
const AEDesc &inRequestedType,
|
||
AEDesc &outPropertyDesc) const
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
OSErr err = noErr;
|
||
NS_NOTYETIMPLEMENTED("Write Me");
|
||
#if 0
|
||
|
||
switch (inProperty)
|
||
{
|
||
case AE_www_typeApplicationAlert: // application that handles alerts
|
||
err = ::AECreateDesc(typeType, &ErrorManager::sAlertApp,
|
||
sizeof(ErrorManager::sAlertApp), &outPropertyDesc);
|
||
ThrowIfOSErr_(err);
|
||
break;
|
||
|
||
case AE_www_typeKioskMode:
|
||
err = ::AECreateDesc(typeLongInteger, (const void *)mKioskMode,
|
||
sizeof(mKioskMode), &outPropertyDesc);
|
||
break;
|
||
|
||
default:
|
||
NS_NOTYETIMPLEMENTED("Write Me");
|
||
// CFrontApp::sApplication->LApplication::GetAEProperty(inProperty, inRequestedType, outPropertyDesc);
|
||
break;
|
||
}
|
||
#endif // 0
|
||
return err;
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
OSErr nsAppleEventHandler::SetAEProperty(DescType inProperty,
|
||
const AEDesc &inValue,
|
||
AEDesc &outPropertyDesc)
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
OSErr err = noErr;
|
||
NS_NOTYETIMPLEMENTED("Write Me");
|
||
#if 0
|
||
switch (inProperty)
|
||
{
|
||
case AE_www_typeApplicationAlert: // application that handles alerts
|
||
try
|
||
{
|
||
OSType newSig;
|
||
UExtractFromAEDesc::TheType(inValue, newSig);
|
||
ErrorManager::sAlertApp = newSig;
|
||
}
|
||
catch(...) // In case of error, revert to self
|
||
{
|
||
ErrorManager::sAlertApp = emSignature;
|
||
}
|
||
break;
|
||
case AE_www_typeKioskMode:
|
||
try
|
||
{
|
||
Boolean menuBarModeChangeBroadcasted = false;
|
||
Int32 kMode;
|
||
UExtractFromAEDesc::TheInt32(inValue, kMode);
|
||
|
||
if ((kMode == KioskOn) && (mKioskMode != KioskOn))
|
||
{
|
||
mKioskMode = KioskOn;
|
||
// SetMenubar(KIOSK_MENUBAR); <20><><EFBFBD> this is currently handled by the chrome structure, below
|
||
// BUT, they want three states for menu bars, and the field is only a boolean
|
||
|
||
CMediatedWindow* theIterWindow = nsnull;
|
||
DataIDT windowType = WindowType_Browser;
|
||
CWindowIterator theWindowIterator(windowType);
|
||
|
||
while (theWindowIterator.Next(theIterWindow))
|
||
{
|
||
CBrowserWindow* theBrowserWindow = dynamic_cast<CBrowserWindow*>(theIterWindow);
|
||
if (theBrowserWindow != nil)
|
||
{
|
||
Chrome aChrome;
|
||
theBrowserWindow->GetChromeInfo(&aChrome);
|
||
aChrome.show_button_bar = 0;
|
||
aChrome.show_url_bar = 0;
|
||
aChrome.show_directory_buttons = 0;
|
||
aChrome.show_security_bar = 0;
|
||
aChrome.show_menu = 0; // <20><><EFBFBD> this isn't designed correctly! deeje 97-03-13
|
||
|
||
// Make sure we only broadcast the menubar mode change once!
|
||
theBrowserWindow->SetChromeInfo(&aChrome, !menuBarModeChangeBroadcasted);
|
||
if (!menuBarModeChangeBroadcasted)
|
||
{
|
||
menuBarModeChangeBroadcasted = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if ((kMode == KioskOff) && (mKioskMode != KioskOff))
|
||
{
|
||
mKioskMode = KioskOff;
|
||
// SetMenubar(MAIN_MENUBAR); <20><><EFBFBD> this is currently handled by the chrome structure, below
|
||
// BUT, they want three states for menu bars, and the field is only a boolean
|
||
|
||
CMediatedWindow* theIterWindow = nsnull;
|
||
DataIDT windowType = WindowType_Browser;
|
||
CWindowIterator theWindowIterator(windowType);
|
||
|
||
while (theWindowIterator.Next(theIterWindow))
|
||
{
|
||
CBrowserWindow* theBrowserWindow = dynamic_cast<CBrowserWindow*>(theIterWindow);
|
||
if (theBrowserWindow != nil)
|
||
{
|
||
Chrome aChrome;
|
||
theBrowserWindow->GetChromeInfo(&aChrome);
|
||
aChrome.show_button_bar = CPrefs::GetBoolean(CPrefs::ShowToolbar);
|
||
aChrome.show_url_bar = CPrefs::GetBoolean(CPrefs::ShowURL);
|
||
aChrome.show_directory_buttons = CPrefs::GetBoolean(CPrefs::ShowDirectory);
|
||
aChrome.show_security_bar = CPrefs::GetBoolean(CPrefs::ShowToolbar) || CPrefs::GetBoolean(CPrefs::ShowURL);
|
||
aChrome.show_menu = 1; // <20><><EFBFBD> this isn't designed correctly! deeje 97-03-13
|
||
|
||
// Make sure we only broadcast the menubar mode change once!
|
||
theBrowserWindow->SetChromeInfo(&aChrome, !menuBarModeChangeBroadcasted);
|
||
if (!menuBarModeChangeBroadcasted)
|
||
{
|
||
menuBarModeChangeBroadcasted = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
catch(...)
|
||
{}
|
||
break;
|
||
default:
|
||
NS_NOTYETIMPLEMENTED("Write Me");
|
||
// CFrontApp::sApplication->LApplication::SetAEProperty(inProperty, inValue, outPropertyDesc);
|
||
break;
|
||
}
|
||
#endif // 0
|
||
return err;
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
// The return value has been AddRefed. Callers should release it.
|
||
nsIWebShellWindow* FindWebShellWindow(nsIXULWindowCallbacks* inCallbacks)
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
// Temporary - we'll create a brand new window EVERY time.
|
||
nsresult rv;
|
||
NS_WITH_SERVICE(nsIAppShellService, appShellService, kAppShellServiceCID, &rv);
|
||
if (NS_FAILED(rv))
|
||
return nsnull;
|
||
|
||
const PRInt32 windowWidth = 615;
|
||
const PRInt32 windowHeight = 650;
|
||
nsCOMPtr<nsIURI> urlObj;
|
||
char * urlStr = "chrome://navigator/content";
|
||
NS_WITH_SERVICE(nsIIOService, service, kIOServiceCID, &rv);
|
||
if (NS_FAILED(rv)) return nsnull;
|
||
|
||
nsIURI *uri = nsnull;
|
||
rv = service->NewURI(urlStr, nsnull, &uri);
|
||
if (NS_FAILED(rv)) return nsnull;
|
||
|
||
rv = uri->QueryInterface(NS_GET_IID(nsIURI), (void**)&urlObj);
|
||
NS_RELEASE(uri);
|
||
if (NS_FAILED(rv))
|
||
return nsnull;
|
||
|
||
nsIWebShellWindow *aWindow = nsnull; // we will return the window AddRefed
|
||
rv = appShellService->CreateTopLevelWindow(
|
||
nsnull,
|
||
urlObj, // nsIURI* of chrome
|
||
PR_TRUE, PR_TRUE,
|
||
NS_CHROME_ALL_CHROME,
|
||
inCallbacks, // callbacks
|
||
NS_SIZETOCONTENT, NS_SIZETOCONTENT,
|
||
&aWindow);
|
||
if (NS_FAILED(rv))
|
||
return nsnull;
|
||
return aWindow;
|
||
}
|
||
|
||
//========================================================================================
|
||
// Implementation of MoreExtractFromAEDesc
|
||
// Apple event helpers -- extension of UExtractFromAEDesc.h
|
||
// All the miscelaneous AppleEvent helper routines.
|
||
//========================================================================================
|
||
|
||
#pragma mark -
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
void MoreExtractFromAEDesc::GetCString(const AppleEvent &inAppleEvent,
|
||
AEKeyword keyword, char * & s, Boolean inThrowIfError)
|
||
// Given an AppleEvent, locate a string given a keyword and
|
||
// return the string
|
||
// In: Event to search
|
||
// AEKeyword assocaated with the string
|
||
// C string ptr
|
||
// Out: Pointer to a newly created C string returned
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
s = nil;
|
||
StAEDescriptor desc;
|
||
OSErr err = ::AEGetParamDesc(&inAppleEvent,keyword,typeWildCard,&desc.mDesc);
|
||
|
||
if (err) {
|
||
if (inThrowIfError)
|
||
ThrowIfOSErr_(err);
|
||
else
|
||
return;
|
||
}
|
||
TheCString(desc, s);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
void MoreExtractFromAEDesc::TheCString(const AEDesc &inDesc, char * & outPtr)
|
||
// Given an AEDesc of type typeChar, return its string.
|
||
// In: AEDesc containing a string
|
||
// C string ptr
|
||
// Out: Pointer to a newly created C string returned
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
outPtr = nil;
|
||
Handle dataH;
|
||
AEDesc coerceDesc = {typeNull, nil};
|
||
if (inDesc.descriptorType == typeChar)
|
||
{
|
||
#if TARGET_CARBON
|
||
DebugStr("\pAppleEvent support needs fixing under Carbon");
|
||
#else
|
||
dataH = inDesc.dataHandle; // Descriptor is the type we want#
|
||
#endif
|
||
}
|
||
else
|
||
{
|
||
// Try to coerce to the desired type
|
||
if (AECoerceDesc(&inDesc, typeChar, &coerceDesc) == noErr)
|
||
{
|
||
// Coercion succeeded
|
||
#if TARGET_CARBON
|
||
DebugStr("\pAppleEvent support needs fixing under Carbon");
|
||
#else
|
||
dataH = coerceDesc.dataHandle;
|
||
#endif
|
||
|
||
}
|
||
else
|
||
return;
|
||
}
|
||
|
||
Int32 strLength = GetHandleSize(dataH);
|
||
outPtr = (char *)PR_MALLOC(strLength+1); // +1 for nsnull ending
|
||
if (!outPtr)
|
||
return;
|
||
// Terminate the string
|
||
BlockMoveData(*dataH, outPtr, strLength);
|
||
outPtr[strLength] = 0;
|
||
|
||
if (coerceDesc.dataHandle != nil)
|
||
AEDisposeDesc(&coerceDesc);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
void MoreExtractFromAEDesc::MakeErrorReturn(
|
||
AppleEvent &event,
|
||
ConstStr255Param errorString,
|
||
OSErr errorCode)
|
||
// Add an error string and error code to an AppleEvent.
|
||
// Typically used when constructing the return event when an
|
||
// error occured
|
||
// In: Apple Event to append to
|
||
// Error string
|
||
// Error code
|
||
// Out: keyErrorNum and keyErrorSting AEDescs are added to the Event.
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
StAEDescriptor errorNum(errorCode);
|
||
StAEDescriptor errorText((ConstStringPtr)errorString);
|
||
// We can ignore the errors. If error occurs, it only means that the reply is not handled
|
||
OSErr err = ::AEPutParamDesc(&event, keyErrorNumber, &errorNum.mDesc);
|
||
err = ::AEPutParamDesc(&event, keyErrorString, &errorText.mDesc);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
Boolean MoreExtractFromAEDesc::DisplayErrorReply(AppleEvent &reply)
|
||
// Display an error dialog if the given AppleEvent contains
|
||
// a keyErrorNumber. a keyErrorString is optional and will be
|
||
// displayed if present
|
||
// In: Apple Event
|
||
// Out: Error dialog displayed if error data present.
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
DescType realType;
|
||
Size actualSize;
|
||
OSErr errNumber;
|
||
Str255 errorString;
|
||
// First check for errors
|
||
errNumber = AEUtilities::EventHasErrorReply(reply);
|
||
if (errNumber == noErr)
|
||
return false;
|
||
|
||
// server returned an error, so get error string
|
||
OSErr err = ::AEGetParamPtr(&reply, keyErrorString, typeChar,
|
||
&realType, &errorString[1], sizeof(errorString)-1,
|
||
&actualSize);
|
||
if (err == noErr)
|
||
{
|
||
errorString[0] = actualSize > 255 ? 255 : actualSize;
|
||
NS_NOTYETIMPLEMENTED("Write Me");
|
||
// ErrorManager::ErrorNotify(errNumber, errorString);
|
||
}
|
||
else
|
||
{
|
||
NS_NOTYETIMPLEMENTED("Write Me");
|
||
// ErrorManager::ErrorNotify(errNumber, (unsigned char *)*GetString(AE_ERR_RESID));
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
ProcessSerialNumber MoreExtractFromAEDesc::ExtractAESender(const AppleEvent &inAppleEvent)
|
||
// Return the process serial number of the sending process.
|
||
// In: Apple Event send by some app.
|
||
// Out: ProcessSerialNumber of the sending app.
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
Size realSize;
|
||
DescType realType;
|
||
TargetID target;
|
||
ProcessSerialNumber psn;
|
||
|
||
OSErr err = AEGetAttributePtr(&inAppleEvent, keyAddressAttr, typeTargetID, &realType,
|
||
&target, sizeof(target), &realSize);
|
||
ThrowIfOSErr_(err);
|
||
err = ::GetProcessSerialNumberFromPortName(&target.name,&psn);
|
||
ThrowIfOSErr_(err);
|
||
return psn;
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
void MoreExtractFromAEDesc::DispatchURLDirectly(const AppleEvent &inAppleEvent)
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
char *url = nsnull;
|
||
MoreExtractFromAEDesc::GetCString(inAppleEvent, keyDirectObject, url);
|
||
ThrowIfNil_(url);
|
||
NS_NOTYETIMPLEMENTED("Write Me");
|
||
#if 0
|
||
URL_Struct * request = NET_CreateURLStruct(url, NET_DONT_RELOAD);
|
||
PR_DELETE(url);
|
||
ThrowIfNil_(request);
|
||
request->internal_url = TRUE; // for attachments in mailto: urls.
|
||
CURLDispatcher::DispatchURL(request, nsnull);
|
||
#endif
|
||
}
|
||
|
||
//========================================================================================
|
||
// Implementation of AEUtilities
|
||
// Some more simple Apple Event utility routines.
|
||
//========================================================================================
|
||
|
||
#pragma mark -
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
OSErr AEUtilities::CreateAppleEvent(OSType suite, OSType id,
|
||
AppleEvent &event, ProcessSerialNumber targetPSN)
|
||
// CreateAppleEvent
|
||
// Create a new Apple Event from scratch.
|
||
// In: Apple Event suite
|
||
// Apple Event ID
|
||
// Ptr to return Apple Event
|
||
// ProcessSerialNumber of the target app to send event to.
|
||
// Out:A new Apple Event is created. More data may be added to
|
||
// the event simply by calling AEPutParamDesc or AEPutParamPtr
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
AEAddressDesc progressApp;
|
||
OSErr err = ::AECreateDesc(typeProcessSerialNumber, &targetPSN,
|
||
sizeof(targetPSN), &progressApp);
|
||
if (err)
|
||
return err;
|
||
err = ::AECreateAppleEvent(suite, id,
|
||
&progressApp,
|
||
kAutoGenerateReturnID,
|
||
kAnyTransactionID,
|
||
&event);
|
||
AEDisposeDesc(&progressApp);
|
||
return err;
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
OSErr AEUtilities::EventHasErrorReply(AppleEvent & reply)
|
||
// Check to see if there is an error in the given AEvent.
|
||
// We simply return an OSError equiv to the error value
|
||
// in the event. If none exists (or an error took place
|
||
// during access) we return 0.
|
||
// In: Apple Event to test
|
||
// Out:Error value returned
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
if (reply.descriptorType == typeNull)
|
||
return noErr;
|
||
|
||
SInt32 errNumber;
|
||
Size realSize;
|
||
DescType realType;
|
||
OSErr err = ::AEGetParamPtr(&reply, keyErrorNumber, typeLongInteger,
|
||
&realType, &errNumber, sizeof(errNumber),
|
||
&realSize);
|
||
if (err == noErr)
|
||
return errNumber;
|
||
else
|
||
return noErr;
|
||
}
|
||
|
||
//========================================================================================
|
||
// InitializeMacCommandLine
|
||
// The only external entry point to this file.
|
||
//========================================================================================
|
||
|
||
#pragma mark -
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
void InitializeMacCommandLine(int& argc, char**& argv)
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
typedef char* charP;
|
||
args = new charP[MAX_TOKENS];
|
||
args[0] = nsnull;
|
||
argc = 0;
|
||
argv = args;
|
||
|
||
// Set up AppleEvent handling.
|
||
|
||
nsAppleEventHandler* handler = nsAppleEventHandler::Get();
|
||
if (!handler)
|
||
return;
|
||
|
||
// Snarf all the odoc and pdoc apple-events.
|
||
//
|
||
// 1. If they are odoc for 'CMDL' documents, read them into the buffer ready for
|
||
// parsing (concatenating multiple files).
|
||
//
|
||
// 2. If they are any other kind of document, convert them into -url command-line
|
||
// parameters or -print parameters, with file URLs.
|
||
|
||
EventRecord anEvent;
|
||
for (int i = 1; i < 5; i++)
|
||
::WaitNextEvent(0, &anEvent, 0, nsnull);
|
||
|
||
while (::EventAvail(highLevelEventMask, &anEvent))
|
||
{
|
||
::WaitNextEvent(highLevelEventMask, &anEvent, 0, nsnull);
|
||
if (anEvent.what == kHighLevelEvent)
|
||
OSErr err = ::AEProcessAppleEvent(&anEvent);
|
||
}
|
||
|
||
// Now we've grabbed all the initial high-level events, and written them into
|
||
// the command-line buffer as url commands, parse the buffer.
|
||
|
||
handler->SetStartedUp(PR_TRUE);
|
||
if (!argBuffer)
|
||
return;
|
||
|
||
// Release some unneeded memory
|
||
char* oldBuffer = argBuffer;
|
||
argBuffer = new char[PL_strlen(argBuffer) + 1];
|
||
PL_strcpy(argBuffer, oldBuffer);
|
||
delete [] oldBuffer;
|
||
|
||
// Parse the buffer.
|
||
int rowNumber = 0;
|
||
char* strtokFirstParam = argBuffer;
|
||
while (argc < MAX_TOKENS)
|
||
{
|
||
// Get the next token. Initialize strtok by passing the string the
|
||
// first time. Subsequently, pass nil.
|
||
char* nextToken = strtok(strtokFirstParam, " \t\n\r");
|
||
args[argc] = nextToken;
|
||
if (!nextToken)
|
||
break;
|
||
// Loop
|
||
argc++;
|
||
strtokFirstParam = nsnull;
|
||
}
|
||
|
||
// Release the unneeded memory.
|
||
if (argc < MAX_TOKENS)
|
||
{
|
||
charP* oldArgs = args;
|
||
int arraySize = 1 + argc;
|
||
args = new charP[arraySize];
|
||
memcpy(args, oldArgs, arraySize * sizeof(charP));
|
||
delete [] oldArgs;
|
||
argv = args;
|
||
}
|
||
} // InitializeMac
|