/**
 * Scout - The Amiga System Monitor
 *
 *------------------------------------------------------------------
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * You must not use this source code to gain profit of any kind!
 *
 *------------------------------------------------------------------
 *
 * @author Andreas Gelhausen
 * @author Richard Körber <rkoerber@gmx.de>
 */



#include "system_headers.h"

#define EXECBASE        (*(struct ExecBase **)4)
#define aprintf         Printf

__asm ULONG main (register __a0 struct WBStartup *);

static char Template[] = TEMPLATE;
static char WBTemplate[] = WBTEMPLATE;

extern struct  ExecBase    *SysBase;

static struct  RDArgs      *rdargs;
static struct  RDArgs      *myRDArgs;
       struct  Args        opts;

struct Process    *proc;
struct WBStartup  *msg;

ULONG __saveds startup (void) {
   ULONG rc;
   BYTE  oldtaskpri = 0;
   BPTR  oldinput = (BPTR)NULL, newinput = (BPTR)NULL, oldoutput = (BPTR)NULL;

   SysBase = EXECBASE;
   rc = RETURN_FAIL;
   proc = (struct Process *) FindTask (NULL);

   if (!(proc->pr_CLI)) {
      WaitPort(&proc->pr_MsgPort);
      msg = (struct WBStartup *) GetMsg (&proc->pr_MsgPort);
   }

   DOSBase = (struct DosLibrary *) OpenLibrary (DOSNAME, 37);
   IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 37);
   UtilityBase = OpenLibrary (UTILITYNAME, 37);

   if (DOSBase && IntuitionBase && UtilityBase) {

      if (msg) {
         struct   Library  *IconBase;
         struct   WBArg    *wbArg;

         /*
          * Started from Workbench so do icon magic...
          *
          * What we will do here is try all of the tooltypes
          * in the icon and keep only those which do not cause
          * errors in the RDArgs.
          */
         if ((wbArg = msg->sm_ArgList) && (IconBase = OpenLibrary (ICONNAME,0))) {
            struct   DiskObject  *diskObj;
                     BPTR        tmplock;

            /*
             * Use project icon if it is there...
             */
            if (msg->sm_NumArgs > 1) wbArg++;

            tmplock = CurrentDir (wbArg->wa_Lock);
            if (diskObj = GetDiskObject (wbArg->wa_Name)) {
               char  **ToolTypes;

               if (ToolTypes = diskObj->do_ToolTypes) {
                  char  *TotalString;
                  ULONG totalSize = 3;

                  while (*ToolTypes) {
                     totalSize += strlen(*ToolTypes)+1;
                     ToolTypes++;
                  }

                  if (TotalString = AllocVec (totalSize,MEMF_PUBLIC)) {
                  char  *CurrentPos = TotalString;
                  ULONG currentLength;

                     ToolTypes = diskObj->do_ToolTypes;
                     do {
                        *CurrentPos='\0';
                        if (*ToolTypes) strcpy (CurrentPos,*ToolTypes);
                        currentLength=strlen(CurrentPos);
                        CurrentPos[currentLength+0]='\n';
                        CurrentPos[currentLength+1]='\0';

                        if (rdargs) FreeArgs(rdargs);
                        memset ((char *) &opts, 0, sizeof(opts));

                        if (myRDArgs) FreeDosObject (DOS_RDARGS,myRDArgs);
                        if (myRDArgs = AllocDosObject (DOS_RDARGS,NULL)) {
                           myRDArgs->RDA_Source.CS_Buffer = TotalString;
                           myRDArgs->RDA_Source.CS_Length = strlen(TotalString);

                           if (rdargs = ReadArgs (WBTemplate, (LONG *) &opts, myRDArgs)) {
                              CurrentPos[currentLength]=' ';
                              CurrentPos+=currentLength+1;
                           }
                        }
                     } while (*ToolTypes++);
                     FreeVec (TotalString);
                  }
               }
               FreeDiskObject (diskObj);
            }

            CurrentDir (tmplock);
            CloseLibrary (IconBase);
         }

         if (newinput = Open ("CON:0/12/400/100/Scout/AUTOCLOSE/WAIT", MODE_READWRITE)) {
            oldinput = SelectInput (newinput);
            oldoutput = SelectOutput (newinput);
         }
         rc = RETURN_OK;
      } else {
         /*
          * Started from CLI so do standard ReadArgs
          */
         if (!(rdargs = ReadArgs (Template, (LONG *) &opts, NULL)))
            PrintFault(IoErr(),NULL);
         else if (SetSignal(0,0) & SIGBREAKF_CTRL_C)
            PrintFault(ERROR_BREAK,NULL);
         else
            rc = RETURN_OK;
      }

      if ((opts.ToolPri) && ((*opts.ToolPri < -128) || (*opts.ToolPri > 127))) {
         Write (Output(),"ToolPri is not in range (-128 - 127).\n",38);
      } else if ((opts.CpuDisplay) && ((*opts.CpuDisplay < 1) || (*opts.CpuDisplay > 2))) {
         Write (Output(),"CpuDisplay is not in range (1 - 2).\n",36);
      } else if ((opts.SortLibrariesType) && ((*opts.SortLibrariesType < 1) || (*opts.SortLibrariesType > 2))) {
         Write (Output(),"SortLibrariesType is not in range (1 - 2).\n",43);
      } else if ((opts.SortDevicesType) && ((*opts.SortDevicesType < 1) || (*opts.SortDevicesType > 2))) {
         Write (Output(),"SortDevicesType is not in range (1 - 2).\n",41);
      } else if ((opts.SortResourcesType) && ((*opts.SortResourcesType < 1) || (*opts.SortResourcesType > 2))) {
         Write (Output(),"SortResourcesType is not in range (1 - 2).\n",43);
      } else if ((opts.SortTasksType) && ((*opts.SortTasksType < 1) || (*opts.SortTasksType > 2))) {
         Write (Output(),"SortTasksType is not in range (1 - 2).\n",39);
      } else if ((opts.SortPortsType) && ((*opts.SortPortsType < 1) || (*opts.SortPortsType > 2))) {
         Write (Output(),"SortPortsType is not in range (1 - 2).\n",39);
      } else if ((opts.SortCommandsType) && ((*opts.SortCommandsType < 1) || (*opts.SortCommandsType > 2))) {
         Write (Output(),"SortCommandsType is not in range (1 - 2).\n",42);
      } else if ((opts.SortAssignsType) && ((*opts.SortAssignsType < 1) || (*opts.SortAssignsType > 2))) {
         Write (Output(),"SortAssignsType is not in range (1 - 2).\n",41);
      } else if ((opts.SortLocksType) && ((*opts.SortLocksType < 1) || (*opts.SortLocksType > 2))) {
         Write (Output(),"SortLocksType is not in range (1 - 2).\n",39);
      } else if ((opts.SortCommoditiesType) && ((*opts.SortCommoditiesType < 1) || (*opts.SortCommoditiesType > 2))) {
         Write (Output(),"SortCommoditiesType is not in range (1 - 2).\n",45);
      } else if ((opts.SortScreenmodeType) && ((*opts.SortScreenmodeType < 1) || (*opts.SortScreenmodeType > 2))) {
         Write (Output(),"SortScreenmodeType is not in range (1 - 2).\n",44);
      } else if ((opts.SortClassesType) && ((*opts.SortClassesType < 1) || (*opts.SortClassesType > 2))) {
         Write (Output(),"SortClassesType is not in range (1 - 2).\n",44);
      } else {       
         if (rc == RETURN_OK) {
            /*
             * Set program priority if requested
             */
            if (opts.ToolPri) {
               oldtaskpri = SetTaskPri ((struct Task *) proc,*opts.ToolPri);
            }

            /*
             * Call the main program
             */
            rc = main (msg);
         }

         /*
          * Reset program priority if necessary
          */
         if (opts.ToolPri) {
            SetTaskPri ((struct Task *) proc,(LONG) oldtaskpri);
         }
      }
      if (rdargs) FreeArgs (rdargs);
      if (myRDArgs) FreeDosObject (DOS_RDARGS,myRDArgs);
   
   } else if (!msg) {
      if (!DOSBase) DOSBase = (struct DosLibrary *) OpenLibrary(DOSNAME,0);
      if (DOSBase) {
         Write (Output(),"Requires Kickstart 2.04 (37.175) or later.\n",43);
      }
   }


   if ((msg) && (newinput)) {

      SelectInput (oldinput);
      SelectOutput (oldoutput);
      Close (newinput);
   }

   /*
    * We do this in order to not crash under 1.3...
    * We do not run under 1.3, but that is another issue.
    */
   if (UtilityBase)  CloseLibrary (UtilityBase);
   if (IntuitionBase)  CloseLibrary ((struct Library *) IntuitionBase);
   if (DOSBase)  CloseLibrary ((struct Library *) DOSBase);

   if (msg) {

      Forbid();
      ReplyMsg ((struct Message *) msg);
   }
   return (rc);
}

void __stdargs _XCEXIT (long mist) {
}
