391 lines
12 KiB
C++
391 lines
12 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (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.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
|
|
#include "nsAppRunner.h"
|
|
#include "nsIAppShellService.h"
|
|
#include "nsRepository.h"
|
|
#include "nsIServiceManager.h"
|
|
#include "xp_core.h"
|
|
#include "xp_mcom.h"
|
|
#include "xp_str.h"
|
|
|
|
// Define Class IDs.
|
|
static NS_DEFINE_IID(kAppRunnerCID, NS_APPRUNNER_CID);
|
|
|
|
// Define Interface IDs.
|
|
static NS_DEFINE_IID(kIAppRunnerIID, NS_IAPPRUNNER_IID);
|
|
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
|
|
|
|
// Generate implementation of nsISupports stuff.
|
|
NS_IMPL_ISUPPORTS(nsAppRunner, kIAppRunnerIID);
|
|
|
|
// ctor
|
|
nsAppRunner::nsAppRunner()
|
|
: mArgc( 0 ), mArg( 0 ) {
|
|
NS_INIT_REFCNT();
|
|
}
|
|
|
|
// dtor
|
|
nsAppRunner::~nsAppRunner() {
|
|
delete [] mArg;
|
|
}
|
|
|
|
/*---------------------------- nsAppRunner::main -------------------------------
|
|
| Initialize, then load and run the app shell. All work is farmed out to |
|
|
| virtual functions to enable customization. | |
|
|
------------------------------------------------------------------------------*/
|
|
NS_IMETHODIMP
|
|
nsAppRunner::main( int argc, char *argv[] ) {
|
|
#if 0
|
|
fprintf( stdout, "nsAppRunner::main entered\n" );
|
|
|
|
for ( int i = 0; i < argc; i++ ) {
|
|
fprintf( stdout, "\targv[%d] = %s\n", i, argv[i] );
|
|
}
|
|
|
|
return NS_OK;
|
|
#else
|
|
nsresult rv = Initialize();
|
|
|
|
if ( rv == NS_OK ) {
|
|
// Load app shell.
|
|
rv = LoadAppShell();
|
|
|
|
if ( rv == NS_OK ) {
|
|
// Execute the shell.
|
|
rv = AppShell()->Initialize();
|
|
|
|
if ( rv == NS_OK ) {
|
|
// Run the shell.
|
|
rv = AppShell()->Run();
|
|
|
|
// Shut it down.
|
|
AppShell()->Shutdown();
|
|
|
|
if ( rv != NS_OK ) {
|
|
DisplayMsg( "nsAppRunner error", "app shell failed to run, rv=0x%lX", rv );
|
|
}
|
|
} else {
|
|
DisplayMsg( "nsAppRunner error", "app shell initialization failed, rv=0x%lX", rv );
|
|
}
|
|
} else {
|
|
char *cid = AppShellCID().ToString();
|
|
DisplayMsg( "nsAppRunner error", "Unable to load app shell (CID=%s), rv=0x%lX", cid, rv );
|
|
delete [] cid;
|
|
}
|
|
} else {
|
|
DisplayMsg( "nsAppRunner error", "Initialize failed, rv=0x%lX", rv );
|
|
}
|
|
|
|
return rv;
|
|
#endif
|
|
}
|
|
|
|
|
|
/*---------------------- NSAppRunner::ParseCommandLine -------------------------
|
|
| Store the command line arguments in data members with minor twiddling to |
|
|
| simplify lookup. |
|
|
------------------------------------------------------------------------------*/
|
|
PRBool nsAppRunner::ParseCommandLine( int argc, char *argv[] ) {
|
|
mArgc = argc;
|
|
|
|
// Allocate array of arg info structures.
|
|
mArg = new Arg[ mArgc ];
|
|
|
|
// Fill in structures.
|
|
for( int i = 0; i < mArgc; i++ ) {
|
|
char *p = argv[i];
|
|
|
|
// "Key" is always the beginning
|
|
mArg[i].key = p;
|
|
|
|
// Bump pointer till we get to null or double quote.
|
|
while ( *p && *p != '"' ) {
|
|
p++;
|
|
}
|
|
|
|
// If not null, get value.
|
|
if ( *p ) {
|
|
*p++ = 0; // Terminate key and advance pointer.
|
|
|
|
// Value starts here.
|
|
mArg[i].value = p;
|
|
|
|
// Strip trailing '"'.
|
|
if ( p[ XP_STRLEN(p) ] == '"' ) {
|
|
p[ XP_STRLEN(p) ] = 0;
|
|
}
|
|
} else {
|
|
// Have value point to this null string.
|
|
mArg[i].value = p;
|
|
}
|
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
}
|
|
|
|
|
|
/*------------------------- nsAppRunner::IndexOfArg ----------------------------
|
|
| Return index of specified argument "key." -1 if not found. |
|
|
------------------------------------------------------------------------------*/
|
|
int nsAppRunner::IndexOfArg( const char *key, PRBool ignoreCase ) {
|
|
int result = -1;
|
|
for( int i = 0; result == -1 && i < mArgc; i++ ) {
|
|
if ( ( ignoreCase && XP_STRCASECMP( key, mArg[i].key ) == 0 )
|
|
||
|
|
( !ignoreCase && XP_STRCMP( key, mArg[i].key ) == 0 ) ) {
|
|
result = i;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
/*---------------------- nsAppRunner::IsOptionSpecified ------------------------
|
|
| Search for key via IndexOfArg and return true iff it is found. |
|
|
------------------------------------------------------------------------------*/
|
|
PRBool nsAppRunner::IsOptionSpecified( const char *key, PRBool ignoreCase ) {
|
|
int index = this->IndexOfArg( key, ignoreCase );
|
|
return index != -1;
|
|
}
|
|
|
|
/*----------------------- nsAppRunner::*ValueForOption -------------------------
|
|
| Search for key via IndexOfArg and return corresponding value if it is found, |
|
|
| 0 otherwise. |
|
|
------------------------------------------------------------------------------*/
|
|
const char *nsAppRunner::ValueForOption( const char *key, PRBool ignoreCase ) {
|
|
const char *result = 0;
|
|
int index = this->IndexOfArg( key, ignoreCase );
|
|
if ( index != -1 ) {
|
|
result = mArg[ index ].value;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
/*------------------------- nsAppRunner::Initialize ----------------------------
|
|
| Default simply returns NS_OK. |
|
|
------------------------------------------------------------------------------*/
|
|
nsresult nsAppRunner::Initialize() {
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
/*--------------------------- nsAppRunner::OnExit ------------------------------
|
|
| Default simply returns the input application return value unmodified. |
|
|
------------------------------------------------------------------------------*/
|
|
nsresult nsAppRunner::OnExit( nsresult rvIn ) {
|
|
return rvIn;
|
|
}
|
|
|
|
|
|
/*------------------------- nsAppRunner::AppShellCID ---------------------------
|
|
| Return the CID for nsAppShell. Long term, get this ID dynamically? |
|
|
------------------------------------------------------------------------------*/
|
|
nsCID nsAppRunner::AppShellCID() const {
|
|
nsCID appShellCID = NS_APPSHELL_SERVICE_CID;
|
|
return appShellCID;
|
|
}
|
|
|
|
|
|
/*------------------------ nsAppRunner::LoadAppShell ---------------------------
|
|
| Create an instance of the app shell (object of class represented by |
|
|
| the CID returned by AppShellCID). |
|
|
------------------------------------------------------------------------------*/
|
|
nsresult nsAppRunner::LoadAppShell() {
|
|
nsIAppShellService *appShell = 0;
|
|
nsIID kIAppShellServiceIID = NS_IAPPSHELL_SERVICE_IID;
|
|
nsresult rv = nsServiceManager::GetService( this->AppShellCID(),
|
|
kIAppShellServiceIID,
|
|
(nsISupports**)&appShell );
|
|
if ( rv == NS_OK ) {
|
|
this->SetAppShell( appShell );
|
|
NS_IF_RELEASE( appShell );
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
|
|
/*-------------------------- nsAppRunner::RunShell -----------------------------
|
|
| Run the app shell. |
|
|
------------------------------------------------------------------------------*/
|
|
nsresult nsAppRunner::RunShell() {
|
|
nsresult result = this->mAppShell->Run();
|
|
return result;
|
|
}
|
|
|
|
|
|
/*-------------------------- nsAppRunner::*AppShell ----------------------------
|
|
| Return the app shell associated with this app runner. |
|
|
------------------------------------------------------------------------------*/
|
|
nsIAppShellService *nsAppRunner::AppShell() const {
|
|
return mAppShell;
|
|
}
|
|
|
|
|
|
/*------------------------- nsAppRunner::DisplayMsg ----------------------------
|
|
| Write out the title and text to stderr. |
|
|
------------------------------------------------------------------------------*/
|
|
void nsAppRunner::DisplayMsg( const char *title, const char *text ) {
|
|
fprintf( stderr, "%s\n", title );
|
|
fprintf( stderr, "%s\n", text );
|
|
return;
|
|
}
|
|
|
|
|
|
/*------------------------- nsAppRunner::DisplayMsg ----------------------------
|
|
| Use svprintf to expand the text+args then display the complete text using |
|
|
| the overloaded version of nsAppRunner::DisplayMsg(). |
|
|
------------------------------------------------------------------------------*/
|
|
static void displayMsg( nsAppRunner &obj, const char *title, const char *text, va_list args ) {
|
|
// Fix this later.
|
|
obj.DisplayMsg( title, text );
|
|
return;
|
|
}
|
|
|
|
|
|
/*------------------------- nsAppRunner::DisplayMsg ----------------------------
|
|
| Convert the extra arguments to a vargs list and invoke the static function |
|
|
| that takes one of those. |
|
|
------------------------------------------------------------------------------*/
|
|
void nsAppRunner::DisplayMsg( const char *title, const char *text, ... ) {
|
|
va_list args;
|
|
va_start( text, args );
|
|
this->DisplayMsg( title, text, args );
|
|
va_end( args );
|
|
return;
|
|
}
|
|
|
|
|
|
/*------------------------ nsAppRunner::&SetAppShell ---------------------------
|
|
| Simply do as directed, return *this. |
|
|
------------------------------------------------------------------------------*/
|
|
nsAppRunner &nsAppRunner::SetAppShell( nsIAppShellService *newAppShell ) {
|
|
// Bump refcount for new shell.
|
|
newAppShell->AddRef();
|
|
|
|
// Release current app shell.
|
|
NS_IF_RELEASE(this->mAppShell);
|
|
|
|
// Attach new one.
|
|
this->mAppShell = newAppShell;
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
#if 0
|
|
// nsAppRunnerFactory
|
|
//
|
|
// Means by which instances are created via nsRepository.
|
|
// This code is somewhat temporary as the CreateInstance should really
|
|
// go in platform-specific code in order to create an instance specific
|
|
// to the platform on which we're running.
|
|
class nsAppRunnerFactory : public nsIFactory {
|
|
public:
|
|
NS_DECL_ISUPPORTS
|
|
|
|
nsAppRunnerFactory();
|
|
|
|
// nsIFactory methods
|
|
NS_IMETHOD CreateInstance(nsISupports *aOuter,
|
|
const nsIID &aIID,
|
|
void **aResult);
|
|
|
|
NS_IMETHOD LockFactory(PRBool aLock);
|
|
|
|
protected:
|
|
virtual ~nsAppRunnerFactory();
|
|
};
|
|
|
|
|
|
nsAppRunnerFactory::nsAppRunnerFactory() {
|
|
NS_INIT_REFCNT();
|
|
}
|
|
|
|
nsAppRunnerFactory::~nsAppRunnerFactory() {
|
|
NS_ASSERTION(mRefCnt == 0, "non-zero refcnt at destruction");
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS(nsAppRunnerFactory, kIFactoryIID);
|
|
|
|
NS_IMETHODIMP
|
|
nsAppRunnerFactory::CreateInstance(nsISupports *aOuter,
|
|
const nsIID &aIID,
|
|
void **aResult) {
|
|
nsresult rv = NS_OK;
|
|
nsAppRunner* newAppRunner;
|
|
|
|
if (aResult == NULL) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
} else {
|
|
*aResult = NULL;
|
|
}
|
|
|
|
if (0 != aOuter) {
|
|
return NS_ERROR_NO_AGGREGATION;
|
|
}
|
|
|
|
NS_NEWXPCOM(newAppRunner, nsAppRunner);
|
|
|
|
if (newAppRunner == NULL) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_ADDREF(newAppRunner);
|
|
rv = newAppRunner->QueryInterface(aIID, aResult);
|
|
NS_RELEASE(newAppRunner);
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsAppRunnerFactory::LockFactory(PRBool aLock)
|
|
{
|
|
// Not implemented in simplest case.
|
|
return NS_OK;
|
|
}
|
|
|
|
extern "C" NS_EXPORT nsresult
|
|
NSGetFactory(const nsCID &cid, nsISupports* servMgr, nsIFactory** aFactory ) {
|
|
nsresult rv = NS_OK;
|
|
|
|
if ( aFactory == 0 ) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
} else {
|
|
*aFactory = 0;
|
|
}
|
|
|
|
nsIFactory* inst = new nsAppRunnerFactory();
|
|
if (0 == inst) {
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
} else {
|
|
NS_ADDREF(inst);
|
|
*aFactory = inst;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
#endif
|