#include <exec/types.h>
#include <intuition/intuition.h>
#include <graphics/gfxbase.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>
#include <workbench/icon.h>
#include <libraries/dosextens.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/icon.h>
#include <proto/dos.h>
#include <string.h>

#define BASEROW 11  /* First Row we can write on */
#define BASECOL 4   /* First column we can write on */
#define EXTRAROW 28 /* Overhead for title bar, sizing gadget, and text height */
#define EXTRACOL 8  /* Overhead for borders */

#define MAXSTRINGS  26
extern struct WBStartup *WBenchMsg;
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *IconBase;
struct NewWindow newwindow = {
  0, 0, 0, 0, /* left, top, width, height - filled in later */
  -1, -1,     /* Detail, block pens */
  NEWSIZE|CLOSEWINDOW|INTUITICKS, /* IDCMP flags */
  WINDOWSIZING|WINDOWDEPTH|WINDOWCLOSE|WINDOWDRAG|
  SIMPLE_REFRESH|ACTIVATE,
  NULL, NULL, NULL, NULL, NULL, /* gadgets, checkmark, title,screen, bitmap */
  30, 30, 99999, 99999, WBENCHSCREEN /* min/max width/height, type */
};

struct IntuiText itext = { 0, 1, JAM1, 0, 0, NULL, NULL, NULL};
struct DiskObject *diskobj;

char *getstr(char **, char *, char *);
char **findtools(char *, BPTR);

#define M_CANTOPEN (getstr(toolptr, "OPENFAIL", "Can't Open the window"))

#define MSG(a) Write(Output(),a,strlen(a))
void main(argc, argv)
int argc;
char **argv;
{
struct Preferences prefs;
short len, rows, cols, x, y;
struct Window *window;
struct IntuiMessage *message;
static short modes[4] = { JAM1, JAM2, COMPLEMENT, INVERSVID };
char *(strings[MAXSTRINGS]);
int count, i;
struct WBArg *wbarg;
char **toolptr, *name, lookup[7];

/* Open all of our libraries that we need */
if ((IntuitionBase = (struct IntuitionBase *)
                     OpenLibrary("intuition.library",0)) == NULL)
   { MSG("intuition.library?"); goto done; }

if ((GfxBase = (struct GfxBase *)
               OpenLibrary("graphics.library",0)) == NULL)
   { MSG("graphics.library?");  goto done; }

if ((IconBase = OpenLibrary("icon.library",0)) == NULL)
   { MSG("icon.library?");      goto done; }

GetPrefs(&prefs, sizeof(struct Preferences));

/* Now figure out where we were called from and get our icon file */
if (argc) /* CLI */
   toolptr = findtools(argv[0],
                       ((struct Process *)FindTask(NULL))->pr_CurrentDir);
else /* Workbench */
   {
   wbarg = &(WBenchMsg->sm_ArgList[WBenchMsg->sm_NumArgs-1]);
   toolptr = findtools(wbarg->wa_Name, wbarg->wa_Lock);
   }

/* See if they gave us a real title for the window */
newwindow.Title = getstr(toolptr, "TITLE",  "No ICON file for TITLE");

/* Now go through and get strings for the table */
strcpy(lookup, "STRINGA");
count = 0;
for (i = 0; i<MAXSTRINGS; i++)
   {
   if ((name = FindToolType(toolptr, lookup)) != NULL)
      strings[count++] = name;
   /* Advance to the next string to look for */
   lookup[6]++;  /* make STRINGA to STRINGB to STRINGC ... */
   }

/* Default when we have no strings to something obvious */
if (count == 0)
   {
   count = 1;
   strings[0] = "Unable to find message strings";
   }

/* Calculate how big to open the window taking into account interlace and */
/* any morerows specifications that they have given                       */
rows = GfxBase->NormalDisplayRows;
cols = GfxBase->NormalDisplayColumns;
if (prefs.LaceWB)
   rows += rows;
newwindow.Width = cols;
newwindow.Height = rows;

if ((window = OpenWindow(&newwindow)) == NULL)
   { MSG(M_CANTOPEN);      goto done; }

/* Account for the border overhead */
rows -= EXTRAROW;  cols -= EXTRACOL;

for(;;) {
   /* Wait for the next event to happen */
   while ((message = (struct IntuiMessage *)GetMsg(window->UserPort)) == NULL)
      Wait(1 << window->UserPort->mp_SigBit);

   switch(message->Class) {
      case CLOSEWINDOW:  goto done; /* They said go away ! */
      case NEWSIZE:      cols = window->Width-EXTRACOL;
                         rows = window->Height-EXTRAROW;      break;
      case INTUITICKS:   break;  /* This lets us process slowly */
      }
   /* Let intuition know we have processed the message */
   ReplyMsg((struct Message *)message);

   /* Set up the string to be displayed (randomly) */
   itext.IText = strings[((rand() >> 2) % count)];
   itext.FrontPen = ((rand() >> 2) & 3);
   itext.BackPen  = ((rand() >> 2) & 3);
   itext.DrawMode = modes[((rand() >> 2) & 3)];

   /* Figure out where to display it safely */
   len = IntuiTextLength(&itext);
   x = BASECOL + ((rand() >> 2) % (cols - len));
   y = BASEROW + ((rand() >> 2) % rows);

   /* Display the string */
   PrintIText(window->RPort, &itext, x, y);
   }

done:
/* Clean up everything */
if (diskobj)
   { FreeDiskObject(diskobj);                        diskobj       = NULL; }
if (window)
   { CloseWindow(window);                            window        = NULL; }
if (GfxBase)
   { CloseLibrary((struct Library *)GfxBase);        GfxBase       = NULL; }
if (IntuitionBase)
   { CloseLibrary((struct Library *)IntuitionBase);  IntuitionBase = NULL; }
if (IconBase)
   { CloseLibrary(IconBase);                         IconBase = NULL;      }
}

char **findtools(name, lock)
char *name;
BPTR lock;
{
BPTR olddir;
char **tools = NULL;
if (lock == NULL) return(NULL);
olddir = CurrentDir(lock);
if ((diskobj = GetDiskObject(name)) != NULL)
   tools = diskobj->do_ToolTypes;
CurrentDir(olddir);
return(tools);
}

char *getstr(toolptr, name, deflt)
char **toolptr, *name, *deflt;
{
char *found;
found = FindToolType(toolptr, name);
return(found ? found : deflt);
}

/* Tricks to make the code smaller */
void MemCleanup(){}
