/************************************************************************
 *
 *             D    R    A    W    L    I    N    E    S
 *   
 *          demonstration of Intuition and IDCMP messages
 *                        By Tom Krotchko
 *          
 *               Draw Lines between mouse clicks (left button)
 *         
 *************************************************************************/

#include <exec/types.h>
#include <intuition/intuition.h>

/* Define an Intuition Structure    */
struct IntuitionBase *IntuitionBase;

/* Define a Graphics Structure      */
struct GfxBase *GfxBase; 

/* Define a structure to get messages from Intuition through the IDCMP */
struct IntuiMessage *message;

/* Intuition and Graphics revision of 0 means that any version of the
   operating system (1.0, 1.1, or 1.2) are acceptable                  */
#define INTUITION_REV 0
#define GRAPHICS_REV  0

/* Define a structure to access the topaz font. This structure will 
   be attached to the screen structure (below).                        */

struct TextAttr MyFont =
   {
    "topaz.font",  /* Font Name   */
    TOPAZ_SIXTY,   /* Font Height */
    FS_NORMAL,     /* Style       */
    FPF_ROMFONT    /* Preferences */
   };

/* Define the structure for the new screen (called NewScreen). This
   screen will be a low-resolution, non-interlace screen (320x200) with
   5 bit planes (32 colors). The font defined in the last structure will
   be attached to this screen in this structure.                       */

struct NewScreen NewScreen =
    {
    0,           /* the left edge               */
    0,           /* the top  edge               */  
    320,         /* Width of the screen         */
    200,         /* Height of the screen        */
    5,           /* Depth - # of bitplanes      */
    0,1,         /* DetailPen, BlockPen         */
    0,           /* ViewMode:                   */
                 /* no INTERLACE or HIRES       */
    CUSTOMSCREEN,/* Type - must be CUSTOMSCREEN */
    &MyFont,     /* Connect the font            */
   "Mouse Paint",/* Title of Screen             */
    NULL,        /* Gadgets                     */
    NULL         /* CustomBitMap                */
    };

 /* The struct Screen will be returned from the OpenScreen function */
  struct Screen *Screen;
 
 /**********************************************************************/
/* Now define the parameters of the window we wish to open. Pay close 
   attention to the Flags and IDCMPFlags.

   The struct NewWindow will be passed to the OpenWindow function  */

  struct NewWindow NewWindow =
      {
        20,  20,  /* LeftEdge, TopEdge   */
       300, 100,  /* Width, Height       */
         0,   1,  /* DetailPen, BlockPen */
       /*          IDCMPFlags            */
       CLOSEWINDOW | MOUSEMOVE | MOUSEBUTTONS,
       /*              Flags             */
       WINDOWCLOSE   | SMART_REFRESH | ACTIVATE    |
       WINDOWSIZING  | WINDOWDRAG    | WINDOWDEPTH |
       NOCAREREFRESH | SIZEBRIGHT    | REPORTMOUSE,

       NULL,      /* First Gadget        */
       NULL,      /* Check Mark          */
       "Click Mouse to Draw Lines",      /* Title of Window */
       NULL,      /* Address of Screen this window is to be attached to
                  - we only know this after we open the Screen          */
       NULL,      /* BitMap              */
       100,  25,  /* MinWidth, MinHeight */
       300, 200,  /* MaxWidth, MaxHeight */
    
       CUSTOMSCREEN, /* Choices are Workbench screen or a custom screen */
       };
 /* The structure Window will be returned from the OpenWindow function */
  struct Window *Window;

main()
{

  LONG x,y,PenColor,LastX,LastY,NowX,NowY,FirstTime;

  PenColor = 0;
  FirstTime = 0;

 /* Open the Intuition library. If this function returns a NULL pointer,
    (zero), something is wrong, the program should exit immediately */

IntuitionBase=(struct IntuitionBase *) 
   OpenLibrary("intuition.library",INTUITION_REV);

if (IntuitionBase == NULL)
   {
   printf("Bad IntuitionBase Open. \n"); 
   exit(FALSE);
   } 
 
/* Open the Graphics library. If this function returns a NULL pointer,
   (zero), something (once again) is wrong. Your program should exit. */

GfxBase=(struct GfxBase *)
  OpenLibrary("graphics.library",GRAPHICS_REV);

if (GfxBase == NULL)
   {
   printf("Bad GfxBase Open.\n"); 
   exit(FALSE);
   }

/* Open the screen. Notice that this line is a compressed version of the
   OpenLibrary() functions shown above. Both ways are acceptable.    */

if ((Screen=(struct Screen *)OpenScreen(&NewScreen))==NULL)
   {
   printf("Bad OpenScreen. \n");
   exit(FALSE);
   }


/* Now that the Screen is open get the address of this new screen, place
   it in the window structure and open the window                    */

NewWindow.Screen = Screen;
 
if ((Window=(struct Window *) OpenWindow(&NewWindow)) == NULL)
    {
    /* If the open window was bad, close the screen                  */
    printf("Bad OpenWindow. Closing Screen. \n");
    CloseScreen(Screen);
    exit(FALSE);
    }


/* The Main Processing Loop                                   
   - this is a do forever loop that will not waste processing cycles */
 for (;;)
 {
     /* Wait until the IDCMP says that the user did something        */

        The Wait() puts this program to sleep until the user does 
        something we asked Intuition to tell us about (using the  IDCMP
        flags).

        This form of the Wait() function is very compact, although a little
        bit (haha) confusing because of the bit shift (<<) operator. */ 
      
     Wait(1<<Window->UserPort->mp_SigBit);
  
     /* The GetMsg() function returns the address of the next message
        waiting into "message". If there are no more messages waiting,
        the function will return a 0, making the while loop false     */
     while(message = GetMsg(Window->UserPort))  
     {
          /* Always check to see whether the user tried to end
             the program.                                            */
          if (message->Class == CLOSEWINDOW)
          {
             /* Its very important to reply to messages !            */
             ReplyMsg(message);
             CloseWindow(Window);
             CloseScreen(Screen);
             CloseLibrary(GfxBase);
             CloseLibrary(IntuitionBase);
             exit(TRUE);
          } /* end if */

          /* Check if the mouse was moved        */
          if (message->Class == MOUSEMOVE)
          {
              NowX = message->MouseX;
              NowY = message->MouseY;

              /* This line prevents the user from drawing in the
                 title bar.                                           */
              if (NowY < 12)
                  NowY = 12;

              ReplyMsg(message);
          } /* end if */

          /* Check if the left mouse button was pressed. If it was, draw 
             a line from the last mouse click, and then increment the
             color.                                                   */
          if (message->Class == MOUSEBUTTONS)
          {
              if (FirstTime == 0)
              /* The first time the Mouse button is pressed, we don't draw
                 a line. Move to this position only, and set the flag */
              {
                  /* The Move() function will move the "Pen"
                     to the position specified               */
                  Move(Window->RPort,NowX,NowY);

                  FirstTime=1;
              }
               else
              {
                  /* Increment the PenColor                  */
                  /* An interesting note: Although you may only have up
                     to 32 colors on a non-HAM screen, SetAPen takes a 
                     value up to 255. According to the Amiga ROM Kernel
                     Reference Manual, this is to allow for future expansions
                     to the hardware (8 bit planes). If Commodore 
                     were to expand the Amiga in this way, it would give the
                     Amiga the same color capabilities as a Macintosh II.
                                                             */
                  PenColor = PenColor + 1;
                  if (PenColor > 32)
                    PenColor = 1;
                  /* Set the A Pen to the specified color    */                      
                  SetAPen(Window->RPort,PenColor);

                  /* Draw a line to the new position         */
                  Draw(Window->RPort,NowX,NowY);

                  /* Move to the new position                */
                  Move(Window->RPort,NowX,NowY);      
              }     
              ReplyMsg(message); 
          } /* end if */
     } /* end while */
 } /* end for */
}  /* End of main procedure */
