//************************************
//
// Name : Launch.c
//
//************************************

//**** Header files

//** OS Include files

#include <exec/memory.h>
#include <workbench/startup.h>
#include <workbench/wbstart.h>
#include <libraries/wbstart.h>
#include <dos/dos.h>
#include <dos/dostags.h>

//** OS function prototypes

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/wbstart_protos.h>
#include <clib/macros.h>

//** OS function inline calls

#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/wbstart_pragmas.h>

//** ANSI C includes

//#include <stdio.h>
#include <string.h>

//** Application include

#include "Prefs.h"
#include "launch.h"
#include "Librarian.h"


//**** Local Storage

static ULONG ConIOTags[] = { SYS_Output, 0, SYS_Input, 0, SYS_Asynch, 1,
			     SYS_UserShell, 1, TAG_DONE };
static ULONG NoIOTags[]  = { SYS_Asynch, 1, SYS_UserShell, 1, TAG_DONE, };


//**** Private Functions

void Launch_WB(struct ProgNode *pn, long argc, struct WBArg *argv) {
  static ULONG mytags[]={
    WBStart_Name,               0L,
    WBStart_DirectoryName,      0L,
    WBStart_Stack,              0L,
    WBStart_Priority,           0L,
    WBStart_ArgumentCount,      0L,
    WBStart_ArgumentList,       0L
  };

  if (NULL==pn) {
    mytags[1]=(ULONG)PrefsProgName;
    mytags[3]=(ULONG)PrefsProgDir;
    mytags[5]=4096;
    mytags[7]=0;
    mytags[9]=0L;
    mytags[11]=0L;
    WBStartTagList( (struct TagItem *)mytags);
  } else {
    mytags[1]=(ULONG)pn->pn_Filename;
    mytags[3]=(ULONG)pn->pn_Directory;
    mytags[5]=MAX(4096,pn->pn_Stack);
    mytags[7]=pn->pn_Priority;
    switch ( pn->pn_LaunchCode & LC_ARG_MASK ) {
      case LC_EACH :
	if (NULL!=argc) {
	  mytags[9]=1L;
	  for ( ; argc-- ; ) {
	    mytags[11]=(ULONG)argv++;
	    WBStartTagList( (struct TagItem *)mytags);
	  } // for
	  break;
	}; // fall through to NONE
      case LC_NONE :
	mytags[9]=0L;
	mytags[11]=0L;
	WBStartTagList( (struct TagItem *)mytags);
	break;
      case LC_ALL  :
	mytags[9]=argc;
	mytags[11]=(ULONG)argv;
	WBStartTagList( (struct TagItem *)mytags);
	break;
      default :
	//intf("Bad ARG (WB)\n");
	break;
    } // switch
  }
} // Launch_WB


int SendMsgToHandler(struct WBStartMsg *wbsm) {
  struct MsgPort *hp;     /* Port of WBStart-Handler */

  /* Try to send a message to the WBStart-Handler */
  Forbid();
    hp=FindPort(WBS_PORTNAME);
    if (hp) PutMsg(hp,wbsm);
  Permit();

  if (hp) {
    /* Get reply message */
    WaitPort(HandlerReply);
    GetMsg(HandlerReply);
  }

  return (hp)?1:0;
} // SendMsgToHandler


void Launch_WB2(struct ProgNode *pn, long argc, struct WBArg *argv) {
  struct WBStartMsg wbsm; /* Message for WBStart-Handler */
  BPTR pl;

  if (NULL==pn) {
    //  should start prefs program
    return;
  }

  pl=Lock(pn->pn_Directory,ACCESS_READ);
  if (pl) {

    /* Build message for WBStart-Handler */
    wbsm.wbsm_Msg.mn_Node.ln_Pri= 0;
    wbsm.wbsm_Msg.mn_ReplyPort  = HandlerReply;
    wbsm.wbsm_Name              = pn->pn_Filename;
    wbsm.wbsm_DirLock           = pl;
    wbsm.wbsm_Stack             = pn->pn_Stack;
    wbsm.wbsm_Prio              = pn->pn_Priority;

    switch ( pn->pn_LaunchCode & LC_ARG_MASK ) {
      case LC_EACH :
	if (NULL!=argc) {
	  wbsm.wbsm_NumArgs=1L;
	  for ( ; argc-- ; ) {
	    wbsm.wbsm_ArgList=argv++;
	    SendMsgToHandler(&wbsm);
	  } // for
	  break;
	}; // fall through to NONE
      case LC_NONE :
	wbsm.wbsm_NumArgs=0;
	wbsm.wbsm_ArgList=NULL;
	SendMsgToHandler(&wbsm);
	break;
      case LC_ALL  :
	wbsm.wbsm_NumArgs           = argc;
	wbsm.wbsm_ArgList           = argv;
	SendMsgToHandler(&wbsm);
	break;
      default :
	//intf("Bad ARG (WB)\n");
	break;
    } // switch

    UnLock(pl);
  } // if Lock

} // Launch_WB2



void MyRun(struct ProgNode *pn, STRPTR cline) {

  STRPTR ConsoleName="CON:0/0/640/128/Output/AUTO/WAIT/CLOSE";
  APTR ConsoleTask=0;

  if (ConIOTags[1]=Open(ConsoleName, MODE_NEWFILE)) {
    struct Process *Proc=((struct Process *)FindTask(0L));
    struct FileHandle *FH;

    ConsoleTask=Proc->pr_ConsoleTask;
    FH=BADDR(ConIOTags[1]);
    SetConsoleTask(FH->fh_Type);
    ConIOTags[3]=Open("*", MODE_OLDFILE);
  }; // if

  if (ConIOTags[1])
    System(cline, (struct TagItem *)&ConIOTags);
  else
    System(cline, (struct TagItem *)&NoIOTags);

  if (ConsoleTask) SetConsoleTask(ConsoleTask);
} // MyRun

void Launch_CLI(struct ProgNode *pn, long argc, struct WBArg *argv) {
  long templsize=0;
  STRPTR templ=NULL;
  long clinesize=0;
  STRPTR cline=NULL;
  BPTR newl,oldl;
  long i,j;
  struct WBArg *ta;
  char *p;
  char *q;


  // Create Template
  templsize=strlen(pn->pn_Directory)+2+strlen(pn->pn_Filename);
  templ=AllocVec(templsize,MEMF_PUBLIC|MEMF_REVERSE);
  strcpy(templ,pn->pn_Directory);
  AddPart( templ, pn->pn_Filename, templsize );
  //intf("Template = '-%s'\n",templ);


  switch ( strstr(templ,"%s")?pn->pn_LaunchCode & LC_ARG_MASK:LC_NONE ) {
    case LC_NONE:
      MyRun(pn,templ);
      break;
    case LC_EACH:
      // Count longest wbarg name
      for ( i=argc, ta=argv; i--; ta++) {
	j=strlen(ta->wa_Name);
	if (j>clinesize) clinesize=j;
      } // for
      // create space for command line
      cline=AllocVec(1+clinesize+templsize,MEMF_PUBLIC|MEMF_REVERSE);
      // copy command part
      p=strstr(templ,"%s");
      *p=0;
      strcpy(cline,templ);
      q=cline+(p-templ);
      p+=2;
      // Launch programs
      for( ; argc-- ; argv++) {
	newl = DupLock(argv->wa_Lock);
	oldl = CurrentDir(newl);
	strcpy(q,argv->wa_Name);
	strcat(q,p);
	MyRun(pn,cline);
	CurrentDir(oldl);
	UnLock(newl);
      } // for
      FreeVec(cline);
      break;
    case LC_ALL:
      {
	char buffer[512];
	// eval size
	for ( i=argc, ta=argv; i--; ta++) {
	  NameFromLock(ta->wa_Lock, buffer, 512);
	  clinesize +=strlen(ta->wa_Name)+strlen(buffer)+2;
	} // for
	// create space for command line
	cline=AllocVec(clinesize+templsize,MEMF_PUBLIC|MEMF_REVERSE);
	// copy command part
	p=strstr(templ,"%s");
	*p=0;
	strcpy(cline,templ);
	// Add each argument
	for ( i=argc, ta=argv; i--; ta++) {
	  NameFromLock(ta->wa_Lock, buffer, 512);
	  AddPart(buffer,ta->wa_Name,512);
	  strcat(cline,buffer);
	  strcat(cline," ");
	} // for
	// copy tail of command line
	strcat(cline,p+=2);
	//intf("%s\n",cline);
	MyRun(pn,cline);
	// CleanUp
	FreeVec(cline);
      } // nada
      break;
    default :
      //intf("Unknown ARG code\n");
      break;
  } // switch
  FreeVec(templ);
} // Launch_CLI

/*
void Launch_Rexx(struct ProgNode *pn, long argc, struct WBArg *argv) {
} // Launch_Rexx

void Launch_Batch(struct ProgNode *pn, long argc, struct WBArg *argv) {
} // Launch_Batch
*/


//**** Aux functions

void Launch(struct ProgNode *pn, long argc, struct WBArg *argv) {
  if (NULL==pn) {
    Launch_WB(pn,argc, argv);
  } else
  switch ( pn->pn_LaunchCode & LC_ENV_MASK ) {
    case LC_WB :
      if (WBStartBase) Launch_WB(pn,argc, argv);
      else             Launch_WB2(pn,argc, argv);
      break;
    case LC_CLI:
      Launch_CLI(pn,argc, argv);
      break;
/*
    case LC_REXX:
      Launch_Rexx(pn,argc, argv);
      break;
    case LC_BATCH:
      Launch_Batch(pn,argc, argv);
      break;
*/
    default:
      //intf("unknown LC_ENV\n");
      break;
  } // switch
} // Launch

//**** End of file

