/*
 *  WICONIFY    A utility that allows you to iconify any Intuition window
 *              on any screen, and to open WB windows on any screen.
 *
 *  wTask.c     Handles creation of NewCLI processes.
 *
 *  Copyright 1990 by Davide P. Cervone, all rights reserved.
 *  You may use this code, provided this copyright notice is kept intact.
 */

#define INTUITION_PREFERENCES_H             /* don't need 'em */
#include <intuition/intuitionbase.h>
#include <libraries/dosextens.h>
#include "wHandler.h"
#include "wMenu.h"


#define MYPROC   ((struct Process *)FindTask(NULL))

struct Segment            /* what a SegList looks like */
{
   ULONG Size;              /* size of this Segment */
   BPTR  NextSeg;           /* BPTR to next SegList entry */
   UWORD Nop;               /* NOP for longword alignment of JMP address */
   UWORD Jmp;               /* JMP to code for child */
   APTR  Address;           /* address of child's code */
};

#define NOP     0x4E71      /* 68000 NOP instruction */
#define JMP     0x4EF9      /* 68000 JMP instruction */


static BPTR *NewCLISegPtr;
static BPTR *EndIconifySegPtr;
extern void GetNewCLI();
extern void EndIconify();

/*
 *  Dummy SegLists that call the GetNewCLI and EndIconify routines
 */

static struct Segment GetNewCLISegment =
{
   sizeof(struct Segment),
   NULL, NOP, JMP, (APTR)&GetNewCLI
};

static struct Segment EndIconifySegment =
{
   sizeof(struct Segment),
   NULL, NOP, JMP, (APTR)&EndIconify
};



/*
 *  IconError()
 *
 *  If there is an active wIconify window,
 *    Set its title to the error message
 *    Make sure the title bar is showing
 */

void IconError(Error)
char *Error;
{
   if (ActiveWindow)
      SetWindowTitles(ActiveWindow,-ONE,Error),
      ShowTitle(ActiveWindow->WScreen,TRUE);
}


/*
 *  DoNewCLI()
 *
 *  Set the WB screen to the current one, so the CLI will open there
 *  Calculate the BPTR to the SegList of the NewCLI routine
 *  Create the process that executes the NewCLI command
 *  If the process failed to open, give a message
 */

void DoNewCLI(theScreen)
WSCREEN *theScreen;
{
   APTR GetNewCLI;
   extern APTR CreateProc();

   NewWBScreen(theScreen);
   NewCLISegPtr = (BPTR *) (((ULONG)(&GetNewCLISegment.NextSeg)) >> 2);
   GetNewCLI = CreateProc("GetNewCLI",5,NewCLISegPtr,StackSize);
   if (GetNewCLI == NULL) IconError("Can't Create NewCLI Process");
}


/*
 *  GetNewCLI()
 *
 *  This routine runs as a separate process so that wIconify will not
 *  be held up during the Execute() command (it may put up a disk requester)
 *  
 *  If the screen is a LORES screen and there is a LoRes CLI command string
 *    Use the LoRes command otherwise use the HiRes command
 *  Change the window pointer of our process so that requesters will come
 *    on the correct screen (the one where the NewCLI will appear)
 *  Bring the screen where the NewCLI will open to front
 *  Open NIL: as the output device
 *  Use the DOS Execute() command to run the command with no input stream
 *    and NIL: as the output stream
 *  If we openned NIL:, close it
 *  This process is now complete and should exit normally
 */

static void GetNewCLI()
{
   char *NewCLICommand;
   long Nil;
   extern long Open();

   if (WBScreen && LoResCLICommand &&
      (WBScreen->Screen->ViewPort.Modes & HIRES) == 0)
         NewCLICommand = LoResCLICommand;
        else
         NewCLICommand = HiResCLICommand;

   Forbid(); 
   if (WBScreen) MYPROC->pr_WindowPtr = (APTR)WBScreen->BackDrop;
   if (WBScreen) ScreenToFront(WBScreen->Screen); else WBenchToFront();
   Permit();
   
   Nil = Open("NIL:",MODE_NEWFILE);
   Execute(NewCLICommand,NULL,Nil);
   if (Nil) Close(Nil);

   Exit(0);
}


/*
 *  DoEndIconify()
 *
 *  Get the BPTR to the SegList for the EndIconify routine
 *  Create the process that will run the wIconify loader (to close wIconify)
 *  If the process could not be created, give a message
 */

void DoEndIconify()
{
   APTR EndIconify;
   extern APTR CreateProc();

   EndIconifySegPtr = (BPTR *) (((ULONG)(&EndIconifySegment.NextSeg)) >> 2);
   EndIconify = CreateProc("EndIconify",5,EndIconifySegPtr,4000L);
   if (EndIconify == NULL) IconError("Can't Create EndIconify Process");
}


/*
 *  EndIconify()
 *
 *  This routine runs as a separate process so that wIconify will not
 *  be held up during the Execute() command (it may put up a disk requester)
 *  
 *  Make sure that system messages will appear on the right screen
 *  Open NIL: for output
 *  Try to run the wIconify program (since the handler does not include
 *    any of the clean up code, we need to get the loader running again
 *    in order to end wIconify)
 *  Close the NIL: device
 *  Our job is complete, so exit
 */

static void EndIconify()
{
   long Nil;
   extern long Open();

   Forbid(); 
   if (WBScreen) MYPROC->pr_WindowPtr = (APTR)WBScreen->BackDrop;
   Nil = Open("NIL:",MODE_NEWFILE);
   Execute("C:RUN >NIL: <NIL: WICONIFY:wIconify <NIL: >NIL:",NULL,Nil);
   if (Nil) Close(Nil);
   Exit(0);
}
