/*
 * Standard Hook Startup Code, to make life easier.
 *
 * To keep hook program sizes down, I recommend using the following
 * program and link steps for your hook (but of course you can do
 * whatever you want to):
 *
 *    lc -v HookProgram
 *    blink DEFINE __main=__tinymain SC SD ND
 *          FROM LIB:c.o+start.o+HookProgram.o
 *          TO HookProgram
 *          LIB LIB:mirage.lib+LIB:amiga.lib+LIB:lc.lib
 */

#include <exec/types.h>
#include <exec/execbase.h>
#include <intuition/intuition.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <scan/hooks.h>

/* C startup provides this one... */
extern struct ExecBase  *SysBase;

/* Scan function library base... */
struct ScanBase         *ScanBase = NULL;

/* These are supplied by Scan... */
struct IntuitionBase    *IntuitionBase = NULL;
struct GfxBase          *GfxBase = NULL;

/* To know whether we have called InitHook() or not... */
static BOOL              hooked_in;

/* Our old current directory... */
static BPTR              old_cd;

/* Old task name... */
static char             *old_name;

/* Hook program defines these... */
extern char             *HookName;
extern char             *HookText;
extern int               HookTextCount;

char                    **HookTextArray = NULL;

static char             **TextArray = NULL;

/*
 * Exit the hook, cleaning up as we go.  Should be used in place of
 * the standard exit() call by the main Hook code.
 */
void hook_exit (int rc)
{
   struct Task *task;

   if (hooked_in) {
      if (HookTextArray) FreeText(HookTextArray, HookTextCount);
      CurrentDir(old_cd);     /* back to our old current directory */
      CleanupHook();
      CloseLibrary((struct Library *)ScanBase);
   }

   task = FindTask(NULL);
   task->tc_Node.ln_Name = old_name;

   exit(rc);
}

/*
 * Can be called by the main Hook code, produces an error message and
 * then exits the hook, cleaning up as appropriate.
 */
void hook_fail (char *msg)
{
   struct EasyStruct easy;
   BOOL we_opened_intui = FALSE;

   if (IntuitionBase == NULL) {
      IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0);
      we_opened_intui = TRUE;
   }

   if (ScanBase) {

      /* If library open, use a scan call... */
      Errorf(msg);

   }
   else {

      if (SysBase->LibNode.lib_Version >= 36) {
         /* Under 2.0 do a pleasant EasyRequest */
         easy.es_StructSize = sizeof(struct EasyStruct);
         easy.es_Flags = 0;
         easy.es_Title = HookName;
         easy.es_TextFormat = "%ls: %ls";
         easy.es_GadgetFormat = "Okay";
         EasyRequest(NULL, &easy, NULL, HookName, msg);
      }
      else {
         /* Will use a jarring alert under 1.3 I guess... */
         char buf[80];
         int le;
         buf[0] = 0;
         buf[1] = 10;
         buf[2] = (50-8)/2+6;
         sprintf(&buf[3], "%ls: %ls", HookName, msg);
         le = (640 - (strlen(&buf[3]) * 8)) / 2;
         buf[strlen(&buf[3])+4] = '\0';
         buf[0] = (le >> 8);
         buf[1] = le & 255;
         DisplayAlert(0x00000000L, buf, 50);
      }

   }

   if (IntuitionBase && we_opened_intui)
      CloseLibrary((struct Library *)IntuitionBase);

   hook_exit(20);
}

/*
 * Hook entry point... this does a little initialization and then calls
 * the main hook entry point, called hook_main().
 *
 * Montage will call us with the name of Montage's function library
 * in argv[1], and arguments to the hook in argv[2] and beyond.
 *
 */
void main (int argc, char **argv)
{
   struct Task *task;

   hooked_in = FALSE;

   task = FindTask(NULL);

   old_name = task->tc_Node.ln_Name;
   task->tc_Node.ln_Name = "ImageFX Hook";

   if (ScanBase == NULL) {
      ScanBase = (struct ScanBase *)OpenLibrary(argv[1], 0);
      if (ScanBase == NULL) {
         /* just in case we're using an old Montage: */
         ScanBase = (struct ScanBase *)OpenLibrary("monty1.library", 0);
         if (ScanBase == NULL)
            hook_fail("Cannot open ImageFX function library.");
      }
   }

   if (!InitHook()) hook_fail("Cannot communicate with ImageFX.");

   /*
    * Change this hook's current directory to that of Mirage.
    */
   old_cd = CurrentDir(ScanBase->sb_CurrentDir);

   hooked_in = TRUE;

   IntuitionBase = ScanBase->IntuitionBase;
   GfxBase = ScanBase->GfxBase;

   if (HookText) {
      HookTextArray = ReadText(HookText, HookTextCount);
   }

   hook_main(argc - 1, &argv[1]);
   hook_exit(0);
}


/*
 * GetStr() - Returns the text associated with a given string index
 *            if available, otherwise returns the default text.
 */
char *GetStr (int index, char *def)
{
   if (HookTextArray)
      return(HookTextArray[index]);
   else
      return(def);
}

