/***********************************************************************
 *
 * $Id: code03e8.c,v 1.3 2002/12/08 11:40:52 mankoff Exp $
 *
 ***********************************************************************
 *
 * PURPOSE: This is a hack that allows a Palm to have multiple
 * personality disorder, where the personalities are customizable
 * based upon the application that is getting launched.
 *
 ***********************************************************************
 *
 * ALGORITHM:
 * [0   ] check if warning bit is set (here? I don't know). Maybe we
 *        should not check here and instead respond to system resets.
 * [I   ] patch the trap to the sysAppLaunch function
 * [II  ] get the CRID of the program that getting launched
 * [III ] compare with the Schizophrenic DB of personalities
 * [IV  ] if ( we should *not* act Schizo for this program )
 *           then: run the regular trap and return
 * [V   ] else: get the personality currently installed
 * [VI  ] get the desired personality for this program [III]
 * [VII ] set a flag/bit (where?) warning that the personality has
          changed. This is to help deal with resets
 * [VIII] install the new personality
 * [IX  ] run the regular trap
 * [X   ] install the previous personality [V]
 * [XI  ] unset the warning bit
 *
 ***********************************************************************
 */

#include <PalmOS.h>
#include "schizophrenic.h"

// function prototypes
void get_set_palm_name(Boolean set, Char *palm_name, UInt16 *palm_id);


// Entry point. This is what gets called by the OS thanks to X-Master.
Err MySysAppLaunch( UInt16 cardNo, LocalID dbID, UInt16 launchFlags,
					UInt16 cmd, MemPtr cmdPBP, UInt32* resultP )
{
  
  Err err = 0;
  Err launchErr = 0;
  UInt16 currentID=0;
  UInt16 userID;
  DmOpenRef db_ref;
  //  DmOpenRef schizophrenicDB; // this is the personality DB

  Prefs *prefs;
  MemHandle recH;
  MemPtr p;
  
  // temporary storage
  MemHandle mhCurrentName, mhAppName;
  //UInt32 currentID;
  Char* currentName, *appName;

  UInt32 temp;
  // get the current address of the trap, then patch it.
  Err (*oldTrap)( UInt16, LocalID, UInt16, UInt16, MemPtr, UInt32* );
  FtrGet( APP_ID, RESOURCE_ID, &temp );
  oldTrap = (Err(*)( UInt16, LocalID, UInt16, UInt16, MemPtr, UInt32* ))temp;

  // We only want to maybe be schizophrenic if its a normal launch
  // command that is being sent. So if its not a normal launch, then
  // just call the previous function we patched.
  if( !( cmd == sysAppLaunchCmdNormalLaunch && sysAppLaunchFlagUIApp ) )
	  return oldTrap(cardNo, dbID, launchFlags, cmd, cmdPBP, resultP);

  mhAppName = MemHandleNew( 41 );
  appName = MemHandleLock( mhAppName );
  // Find the creatorID, type and name
  err = DmDatabaseInfo( cardNo, dbID, appName, NULL, NULL, NULL,
						NULL, NULL, NULL, NULL, NULL, NULL, NULL );
  if ( err ) return oldTrap(cardNo, dbID, launchFlags, cmd, cmdPBP, resultP);

  // check if the user has configured any personalities (does the DB exist?)
  db_ref = DmOpenDatabaseByTypeCreator( 'DATA', 'Schz', dmModeReadOnly );
  if ( err || !db_ref ) 
	return oldTrap(cardNo, dbID, launchFlags, cmd, cmdPBP, resultP);

  // otherwise, if we are here, it means that a schizophrenic DB exists
  // so... read it into the prefs struct
  prefs = MemPtrNew( sizeof( Prefs ) );
  recH = DmQueryRecord( db_ref, 0 );
  p = MemHandleLock( recH );
  MemMove( prefs, p, sizeof( Prefs ) );
  MemPtrUnlock( p );
  err = DmCloseDatabase( db_ref );

  // this app is not the app in the DB
  if ( StrCompare( appName, prefs->application ) )
	return oldTrap(cardNo, dbID, launchFlags, cmd, cmdPBP, resultP);
  
  // if here, the current app is the one we want to be schizophrenic for.

  // get the current personality
  mhCurrentName = MemHandleNew( 41 );
  currentName = MemHandleLock( mhCurrentName ); 
  get_set_palm_name( 0, currentName, &currentID );
  // install the new personality
  userID = StrAToI( prefs->userID );
  get_set_palm_name( 1, prefs->userName, &userID );

  // call the previous trap
  launchErr = oldTrap(cardNo, dbID, launchFlags, cmd, cmdPBP, resultP);
  if ( launchErr ) 
	{
	  err = MemHandleUnlock( mhCurrentName );
	  err = MemHandleFree( mhCurrentName );
	  return launchErr;
	}

  // re-install the previous personality.
  get_set_palm_name( 1, currentName, &currentID );
  err = MemHandleUnlock( mhCurrentName );
  err = MemHandleFree( mhCurrentName );

  // clean up
  return launchErr;
}


