/*   This program was hacked from Display v1.06 by Carolyn
 *   Scheppner for inclusion into the Mandelbrot Adventure
 *   Kit.  I have renamed this program Loadit.  Simple and
 *   sweet.
 * 
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/tasks.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <intuition/intuition.h>
#include <graphics/gfxbase.h>

#include "iff/ilbm.h"
#include "myreadpict.h"

#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif  MIN

#define MAK_PIC 0
#define MAP_PIC 1
#define TITLE_PIC 2

/* Bits we must mask out of CAMG.Viewmodes */
#define BADFLAGS  (SPRITES|VP_HIDE|GENLOCK_AUDIO|GENLOCK_VIDEO)
#define FLAGMASK  (~BADFLAGS)
#define CAMGMASK  (FLAGMASK & 0x0000FFFFL)

/* general usage pointers */

extern struct GfxBase  *GfxBase;
extern struct IntuitionBase  *IntuitionBase;
extern struct TextAttr  Font;
extern struct Window *file_window, *FirstWindow;
extern struct IntuiText ok_request, prompt;
extern USHORT *Pointer, *Sleepy, *Cross;
extern UWORD POINTER_col[];
extern UWORD CROSS_col[];
extern UWORD SLEEPY_col[];
ULONG  IconBase = 0;

/* Globals for displaying an image */

struct Screen   *screen1;
struct Window   *window1;
struct ViewPort *vport1;

struct BitMap   tBitMap;      /* Temp BitMap struct for small pics  */

int titleFlag;

/* Structures for new Screen, new Window */

struct   NewScreen      ns = {
   0, 0,                                  /* LeftEdge and TopEdge   */
   640, 400,                              /* Width and Height       */
   4,                                     /* Depth                  */
   1, 0,                                  /* DetailPen and BlockPen */
   NULL,                                  /* Special display modes  */
   CUSTOMSCREEN,                          /* Screen Type            */
   &Font,                                 /* Use my font            */
   " <- Click here (after clicking below) when done viewing.", /* Title */
   NULL,                                  /* No gadgets yet         */
   NULL,                                  /* Ptr to CustomBitmap    */
   };

struct   NewWindow      nw = {
   0, 0,                                  /* LeftEdge and TopEdge */
   640, 400,                              /* Width and Height */
   0, 1,                                  /* DetailPen and BlockPen */
   MOUSEBUTTONS,                          /* IDCMP Flags */
   BACKDROP|
   BORDERLESS|ACTIVATE,                   /* Flags */
   NULL, NULL,                            /* Gadget and Image pointers */
   NULL,                                  /* Title string */
   NULL,                                  /* Put Screen ptr here */
   NULL,                                  /* SuperBitMap pointer */
   0, 0,                                  /* MinWidth and MinHeight */
   0, 0,                                  /* MaxWidth and MaxHeight */
   CUSTOMSCREEN,                          /* Type of window */
   };

USHORT  allBlack[maxColorReg] = {0};

ILBMFrame   iFrame;       /* my global frame */


LoadIt(ilbm_file, showFlag)
char *ilbm_file;
int showFlag;
   {
   IFFP iffp = NO_FILE;
   LONG LoadILBMFile;
   struct IntuiMessage *msg;
   ULONG class, code;
   SHORT mouseX, mouseY;
   int error; 
   char message[40];   
   BOOL TBToggle = FALSE, doneViewing = FALSE;
     
   titleFlag = showFlag;
   
   if(!(LoadILBMFile = Open(ilbm_file, MODE_OLDFILE)))
      {
        strcpy(message, "Picture file not found");
        prompt.IText = message;
        AutoRequest(file_window, &prompt, &ok_request, NULL,
                                  NULL, NULL, 320, 72);
        return(FALSE);
      }                          
   
   iffp = myReadPicture(LoadILBMFile, &iFrame);
   Close(LoadILBMFile);
   if (!(iffp == IFF_DONE))
      {
        strcpy(message, "Not an IFF ILBM");
        prompt.IText = message;
        AutoRequest(file_window, &prompt, &ok_request, NULL,
                                  NULL, NULL, 320, 72);
        return(FALSE);
      } 

   error = DisplayPic(&iFrame);
   if(error)  
      {
        strcpy(message, "Can't open screen or window"); 
        prompt.IText = message;
        AutoRequest(file_window, &prompt, &ok_request, NULL,
                                  NULL, NULL, 320, 72);
        return(FALSE);
      }          

   if(titleFlag == MAK_PIC || titleFlag == MAP_PIC)
     {
      if(titleFlag == MAK_PIC)
        {
         SetColors( 1 );
         ClearPointer(window1);
         SetPointer(window1,Pointer,16,16,0,0);
        }
        
      if(titleFlag == MAP_PIC)  
        {
         SetColors( 2 );
         ClearPointer(window1);
         SetPointer(window1,Cross,16,16,-8,-8);
        }     
      
      while(!(doneViewing))
        {
         while(msg=(struct IntuiMessage *)GetMsg(window1->UserPort))
            {
             class = msg->Class;
             code  = msg->Code;
             mouseX = msg->MouseX;
             mouseY = msg->MouseY;
         
             ReplyMsg(msg);
             switch(class)
               {
                case MOUSEBUTTONS:  
                 if((code == SELECTDOWN) && (mouseX < 10)
                     && (mouseY < 10))
                   {
                    doneViewing = TRUE;
                   }
                 else if((code == SELECTDOWN) && (mouseX > 10)
                          && (mouseY > 10) && (TBToggle == FALSE))
                        {
                         TBToggle = TRUE;
                         ShowTitle(screen1, TRUE); 
                        }  
                 else if((code == SELECTDOWN) && (mouseY > 10)
                          && (TBToggle == TRUE))
                        {  
                         TBToggle = FALSE;
                         ShowTitle(screen1, FALSE);
                        }  
                 break;           
               }
            }   
        }
      ClearPointer(window1);  
      CloseWindow(window1);
      CloseScreen(screen1);
      return(TRUE);  
     }    
     
    if(titleFlag == TITLE_PIC)
      {
        Delay(400);
        CloseWindow(window1);
        CloseScreen(screen1);
        return(TRUE);
      }     
   }


/** getBitMap() *********************************************************
 *
 * Open screen or temp bitmap.
 *   Returns ptr destBitMap  or  0 = error
 *
 *************************************************************************/
struct BitMap *getBitMap(ptilbmFrame)
   ILBMFrame *ptilbmFrame;
   {
   int     i, nPlanes, plsize;
   SHORT  sWidth, sHeight, dWidth, dHeight;
   struct BitMap *destBitMap;

   sWidth  = ptilbmFrame->bmHdr.w;
   sHeight = ptilbmFrame->bmHdr.h;
   dWidth  = ptilbmFrame->bmHdr.pageWidth;
   dHeight = ptilbmFrame->bmHdr.pageHeight;
   nPlanes = MIN(ptilbmFrame->bmHdr.nPlanes, EXDepth);
   ns.Depth = nPlanes;
   
   if (ptilbmFrame->foundCAMG)
      {
      ns.ViewModes = ptilbmFrame->camgChunk.ViewModes & CAMGMASK;
      }
   else
      {
      if (ptilbmFrame->bmHdr.pageWidth >= 640)
         ns.ViewModes = HIRES;
      else
         ns.ViewModes = 0;

      if (ptilbmFrame->bmHdr.pageHeight >= 400)
         ns.ViewModes |= LACE;
      }
   

   if ((screen1 = (struct Screen *)OpenScreen(&ns))==NULL)    return(0);

   vport1 = &screen1->ViewPort;
   LoadRGB4(vport1, &allBlack[0], MIN(1<<ns.Depth,maxColorReg)); 
   nw.Screen = screen1;

   if ((window1 = (struct Window *)OpenWindow(&nw))==NULL)
      {
      CloseScreen(screen1);
      screen1 = NULL;
      return(0);
      }

   if(titleFlag == MAK_PIC || titleFlag == MAP_PIC)
     {
      SetColors( 3 );
      ClearPointer(window1);
      SetPointer(window1,Sleepy,25,16,0,0);
     }  
   
   if ((sWidth == dWidth) && (sHeight == dHeight))
      {
      destBitMap = (struct BitMap *)screen1->RastPort.BitMap;
      }
   else
      {
      InitBitMap( &tBitMap,
                  nPlanes,
                  sWidth,
                  sHeight);

      plsize = RowBytes(ptilbmFrame->bmHdr.w) * ptilbmFrame->bmHdr.h;
      if (tBitMap.Planes[0] =
       (PLANEPTR)AllocMem(nPlanes * plsize, MEMF_CHIP))
         {
         for (i = 1; i < nPlanes; i++)
            tBitMap.Planes[i] = (PLANEPTR)tBitMap.Planes[0] + plsize*i;
         destBitMap = &tBitMap;
         }
      else
         {
         CloseWindow(window1);
         window1 = NULL;
         CloseScreen(screen1);
         screen1 = NULL;
         return(0);  /* can't allocate temp BitMap */
         }
      }
   return(destBitMap);          /* destBitMap allocated */
   }


/** DisplayPic() *********************************************************
 *
 * Display loaded bitmap.  If tBitMap, first transfer to screen.
 *
 *************************************************************************/
DisplayPic(ptilbmFrame)
   ILBMFrame *ptilbmFrame;
   {
   int    i, row, byte, nrows, nbytes;
   struct BitMap  *tbp, *sbp; /* temp and screen BitMap ptrs */
   UBYTE  *tpp, *spp;         /* temp and screen plane ptrs  */

   if (tBitMap.Planes[0])     /* transfer from tBitMap if nec. */
      {
      tbp = &tBitMap;
      sbp = screen1->RastPort.BitMap;
      nrows  = MIN(tbp->Rows, sbp->Rows);
      nbytes = MIN(tbp->BytesPerRow, sbp->BytesPerRow);

      for (i = 0; i < sbp->Depth; i++)
         {
         tpp = (UBYTE *)tbp->Planes[i];
         spp = (UBYTE *)sbp->Planes[i];
         for (row = 0; row < nrows; row++)
            {
            tpp = tbp->Planes[i] + (row * tbp->BytesPerRow);
            spp = sbp->Planes[i] + (row * sbp->BytesPerRow);
            for (byte = 0; byte < nbytes; byte++)
               {
               *spp++ = *tpp++;
               }
            }
         }
      /*  Can now deallocate the temp BitMap  */
      FreeMem(tBitMap.Planes[0],
                 tBitMap.BytesPerRow * tBitMap.Rows * tBitMap.Depth);
      }

   vport1 = &screen1->ViewPort;
   LoadRGB4(vport1, ptilbmFrame->colorMap, ptilbmFrame->nColorRegs);
   return(0);
   }

SetColors( Pointer )
int Pointer;
  {
   SHORT i;
   UWORD red, green, blue;
   
   if( Pointer == 1 )
     {
      for (i = 0; i < 3; i++)
        {
         red = (POINTER_col[i] & 0xf00) >> 8;
         green = (POINTER_col[i] & 0x0f0) >> 4;
         blue = (POINTER_col[i] & 0x00f);
         SetRGB4(vport1,i + 17,red,green,blue);
        }
      return(0);
     }

   if( Pointer == 2)
     {
      for (i = 0; i < 3; i++)
       {
        red = (CROSS_col[i] & 0xf00) >> 8;
        green = (CROSS_col[i] & 0x0f0) >> 4;
        blue = (CROSS_col[i] & 0x00f);
        SetRGB4(vport1,i + 17,red,green,blue);
       }
      return(0);
     }

   if( Pointer == 3)
     {
      for (i = 0; i < 3; i++)
        {
         red = (SLEEPY_col[i] & 0xf00) >> 8;
         green = (SLEEPY_col[i] & 0x0f0) >> 4;
         blue = (SLEEPY_col[i] & 0x00f);
         SetRGB4(vport1,i + 17,red,green,blue);
        }
      return(0);
     }
  }
