/*
 *  WEXAMPLE2.C     Example program for wIconify.
 *                  This program uses an icon with an IconPort to monitor
 *                  most of the IconMessages classes.
 */

#define INTUITION_PREFERENCES_H             /* don't need 'em */
#include <intuition/intuition.h>

#include "wIcon.h"

/*
 *  The revision levels needed to the libraries
 */

#define INTUITION_REV   0
#define GRAPHICS_REV    0
extern struct IntuitionBase *IntuitionBase;
extern struct GfxBase *GfxBase;


/*
 *  Return codes for error and OK
 */

#define ERROR_EXIT      10
#define OK_EXIT         0


/*
 *  Some routines we need
 */

extern struct Window *OpenWindow();
extern struct Node *GetMsg();
extern struct MsgPort *CreatePort();
extern APTR OpenLibrary();


/*
 *  Types of IconMessage to report
 */

#define REPORTFLAGS\
  (WI_REPORTICONIFIED| WI_REPORTRESTORE| WI_REPORTSELECT| WI_REPORTUNSELECT|\
   WI_REPORTPRESS| WI_REPORTRELEASE| WI_REPORTMOVED| WI_REPORTCLOSE|\
   WI_REPORTNEWSCREEN| WI_REPORTSCREENCLOSE| WI_REPORTICONEND|\
   WI_REPORTACTIVATE| WI_REPORTINACTIVE)

/*
 *  The definition for our window
 */

static struct NewWindow NewWindow =
{
   160,50, 320,100, 0,1, CLOSEWINDOW| REFRESHWINDOW,
   WINDOWCLOSE| WINDOWDRAG| WINDOWDEPTH| WINDOWSIZING| SIMPLE_REFRESH,
   NULL, NULL, "wExample2", NULL, NULL, 20,10, -1,-1, WBENCHSCREEN
};
static struct Window *myWindow;


/*
 *  This is the icon definition.  It uses the default imagery and flags,
 *  but adds a lot of report flags.
 */

static WICON myIcon =
{
   NULL,                /* No special name (default is the window name) */
   NULL,NULL,NULL,      /* Use default Image, Select, and Mask */
   0,0,                 /* Let wIconify place it where it wants */
   0,                   /* No special flags  */
   REPORTFLAGS,         /* The special report flags needed */
   NULL                 /* We'll add the icon port once it is created */
};


/*
 *  The Icon port
 */

static struct MsgPort *IconPort;



/*
 *  CleanupIconPort()
 *
 *  If the icon port was allocated
 *    Reply any messages waiting in the port
 *    Delete the port
 */

static void CleanupIconPort()
{
   struct wIconMessage *theMessage;
   
   if (IconPort)
   {
      while (theMessage = (struct wIconMessage *)GetMsg(IconPort))
         ReplyMsg(theMessage);
      DeletePort(IconPort);
   }
}


/*
 *  DoExit()
 *
 *  Print an error message, if necessary, and then clean up any allocated
 *  memory, close the windows and libraries, etc.  Finally, exit.
 */

static void DoExit(s,x1,x2,x3)
char *s, *x1,*x2,*x3;
{
   int status = OK_EXIT;

   if (s)
   {
      printf(s,x1,x2,x3);
      printf("\n");
      status = ERROR_EXIT;
   }
   if (myWindow)        CloseWindow(myWindow);
   if (IconPort)        CleanupIconPort();
   if (IntuitionBase)   CloseLibrary(IntuitionBase);
   if (GfxBase)         CloseLibrary(GfxBase);
   exit(status);
}


/*
 *  CheckLibOpen()
 *
 *  Check to see if the specified library can be openned, and exit with
 *  an error if not.
 */

static void CheckLibOpen(lib,name,rev)
APTR *lib;
char *name;
int rev;
{
   extern APTR OpenLibrary();
   
   if ((*lib = OpenLibrary(name,(ULONG)rev)) == NULL)
      DoExit("Can't open '%s'",name);
}


/*
 *  GetPort()
 *
 *  Create the port and attach it to the icon.
 */

static void GetPort()
{
   IconPort = CreatePort(0,0);
   if (IconPort == NULL) DoExit("Can't Create IconPort");
   myIcon.IconPort = IconPort;
}
  

/*
 *  OpenMyWindow()
 *
 *  Attempt to open the window (error if unsuccessful).
 *  Add the icon to the window once it's open, then iconify the window.
 */

static void OpenMyWindow()
{
   myWindow = OpenWindow(&NewWindow);
   if (myWindow == NULL) DoExit("Can't open my window");
   wSetIcon(myWindow,&myIcon);
   wIconify(myWindow);
}


/*
 *  DisplayMessage()
 *
 *  Set the pen color, and write out the message telling the user
 *  what he should do with this window.
 */

static void DisplayMessage()
{
   struct RastPort *rp = myWindow->RPort;

   SetAPen(rp,3);
   Move(rp,110,43);
   Text(rp,"Iconify Me!",11);
   Move(rp,42,59);
   Text(rp,"(Close me when you're done.)",28);
}


/*
 *  WaitForAction()
 *
 *  While there is still more to do
 *    Wait for a message to arrive at the window's UserPort
 *    While there are more messages in the port
 *      If the message class is a CLOSEWINDOW message, we're done
 *      If its a REFRESH message, draw the text again.
 *      Reply to the message
 *    While there are more IconMessages in the port
 *      Tell the user about the event
 *      Reply to the message
 */

static void WaitForAction()
{
   struct IntuiMessage *intuiMessage;
   struct wIconMessage *iconMessage;
   short NotDone = TRUE;
   struct MsgPort *thePort = myWindow->UserPort;
   long SignalMask = (1 << thePort->mp_SigBit) | (1 << IconPort->mp_SigBit);
   WORD x,y;

   while (NotDone)
   {
      Wait(SignalMask);
      while (intuiMessage = (struct IntuiMessage *)GetMsg(thePort))
      {
         switch(intuiMessage->Class)
         {
            case CLOSEWINDOW:
               NotDone = FALSE;
               break;

            case REFRESHWINDOW:
               BeginRefresh(myWindow);
               DisplayMessage();
               EndRefresh(myWindow);
               break;
         }
         ReplyMsg(intuiMessage);
      }
      while (iconMessage = (struct wIconMessage *)GetMsg(IconPort))
      {
         switch(iconMessage->Action)
         {
            case WI_REPORTICONIFIED:
               printf(">> Window has been Iconified\n");
               break;

            case WI_REPORTRESTORE:
               printf(">> Window has been Restored\n");
               break;

            case WI_REPORTSELECT:
               printf(">> Icon Selected\n");
               break;

            case WI_REPORTUNSELECT:
               printf(">> Icon Unselected\n");
               break;

            case WI_REPORTPRESS:
               printf(">> Icon Pressed\n");
               break;

            case WI_REPORTRELEASE:
               printf(">> Icon Released\n");
               break;

            case WI_REPORTMOVED:
               wIconXY(iconMessage->Icon,&x,&y);
               printf(">> Icon Moved To (%d,%d)\n",x,y);
               break;

            case WI_REPORTCLOSE:
               printf(">> Closing Icon\n");
               wModifyReport(iconMessage->Icon,0);
               NotDone = FALSE;
               break;

            case WI_REPORTNEWSCREEN:
               printf(">> New Screen\n");
               break;

            case WI_REPORTSCREENCLOSE:
               printf(">> Screen Closing\n");
               break;

            case WI_REPORTACTIVATE:
               printf(">> Iconify Backdrop Window Activated\n");
               break;

            case WI_REPORTINACTIVE:
               printf(">> Iconify Backdrop Window Inactive\n");
               break;

            case WI_REPORTICONEND:
               printf(">> Iconify Ending\n");
               break;
         }
         ReplyMsg(iconMessage);
      }
   }
}


/*
 *  main()
 *
 *  If wIconify is running
 *    Open the libraries needed by the program
 *    Create the IconPort
 *    Open the window and add its icon
 *    Display the message in the window
 *    Wait for something to happen
 *  Otherwise
 *    Print an error message
 *  Clean up afterwords
 */

void main()
{
   if (wIconifyActive())
   {
      CheckLibOpen(&IntuitionBase,"intuition.library",INTUITION_REV);
      CheckLibOpen(&GfxBase,"graphics.library",GRAPHICS_REV);
      GetPort();
      OpenMyWindow();
      DisplayMessage();
      printf("wExample2 window is open and iconified\n");
      WaitForAction();
   } else printf("wIconify not running or version mismatch\n");
   DoExit(NULL);
}
