/***********************************************************************/
/* WACOM-Digitizer Driver            (C) 1993-1996 by ROLAND SCHWINGEL */
/***********************************************************************/
/* Demoprogram that shows the usage of the FORBIDSCREEN feature of the */
/* drivers active API.                                                 */
/*                                                                     */
/* Lets you draw in a window on a customscreen without a mouse.        */
/***********************************************************************/

/* INCLUDES ************/
#include <stdio.h>
#include <string.h>
#include <math.h>

#include <exec/exec.h>
#include <proto/exec.h>
#include <clib/exec_protos.h>

#include <dos/dos.h>
#include <proto/dos.h>
#include <clib/dos_protos.h>

#include <intuition/intuition.h>
#include <intuition/IntuitionBase.h>
#include <proto/intuition.h>
#include <clib/intuition_protos.h>

#include <graphics/gfx.h>
#include <proto/graphics.h>
#include <clib/graphics_protos.h>

#include <libraries/gadtools.h>
#include <proto/gadtools.h>
#include <clib/gadtools_protos.h>

#include "Wacom.h"             /* here is all the Wacomdata defined */

/* global Variables ****/
/* external */
extern struct ExecBase           *SysBase;

/* local */
struct IntuitionBase             *IntuitionBase;
struct GfxBase                   *GfxBase;

struct TextAttr DefFont={(STRPTR)"topaz.font",TOPAZ_EIGHTY,FS_NORMAL     ,FPF_ROMFONT};

/* Version-Tag ***************************/
UBYTE *vers="$VER:AvoidScreenDemo 1.1 "__AMIGADATE__" by Roland Schwingel.";

/* Prototypes **********/
int                   main(void);

/***********************************************************************/
/* main()                                                              */
/***********************************************************************/
int main (void)
{
int                         retval=21;
struct MsgPort             *Wacom_data_Port;      /* This is the way where we get the Data */
struct MsgPort             *Our_Port;
struct WacomMSG             WCommandMess,WDataMess;
struct WacomMSG            *WMess;
struct Window              *Win;
struct Screen              *Demoscreen;
struct RastPort            *WinRP;
struct IntuiMessage        *IMess;
ULONG                       screenwidth,screenheight,oldx,oldy,x,y;
LONG                        oldpen;
WORD                        pens[] = { ~0 };
BOOL                        cont=TRUE,Unregister_API=TRUE;
ULONG                       class,Sigrcvd,Sigmask,WinSig,PortSig;

 /* First clear WMess and setup some variables */
 memset(&WCommandMess,0,sizeof(struct WacomMSG));
 oldx=oldy=0;

 /* Now check if our MsgPort is here - means if Wacom Driver program is running */
 if(Wacom_data_Port=FindPort(WACOM_PORT_NAME))
 {
  /* Open graphics.library */
  if(GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37))
  {
   /* Now open intution.library */
   if(IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37L))
   {
    /* Open Custom Screen */
    if(Demoscreen=OpenScreenTags(NULL,SA_Left,0,SA_Top,0,SA_Overscan,OSCAN_TEXT,
				      SA_Depth,2,SA_Pens,pens,SA_Title,"AvoidScreenDemo",
				      SA_Type,CUSTOMSCREEN,SA_DisplayID,HIRESLACE_KEY,
				      SA_Font,&DefFont,TAG_DONE))
    {
     /* Get Screen Dimensions */
     screenwidth=Demoscreen->Width;
     screenheight=Demoscreen->Height;

     /* open the Window */
     if(Win=OpenWindowTags(NULL,WA_Left,0,WA_Top,0,WA_Width,screenwidth,WA_Height,screenheight,
				WA_IDCMP,        IDCMP_CLOSEWINDOW,
				WA_Flags,        WFLG_DRAGBAR|WFLG_CLOSEGADGET|WFLG_SMART_REFRESH|WFLG_ACTIVATE,
				WA_CustomScreen, Demoscreen,
				WA_Title,        "AvoidScreenDemo (Paint with Tablet: Button1=Draw Button2=Clear Drawing)", TAG_DONE))
     {
      /* Get the Rastport and the Sigbit of the Window */
      WinRP=Win->RPort;
      WinSig=1L<<Win->UserPort->mp_SigBit;

      /* Get pen for pixel redrawing */
      oldpen=ReadPixel(WinRP,oldx,oldy);

      /* Install our MessagePort */
      if(Our_Port=CreateMsgPort())
      {
       /* Get Port signal */
       PortSig=1L<<Our_Port->mp_SigBit;

       /* Set up the Message */
       WCommandMess.Mess.mn_Node.ln_Type=NT_MESSAGE;
       WCommandMess.Mess.mn_Length=sizeof(struct WacomMSG);
       WCommandMess.Mess.mn_ReplyPort=Our_Port;

       /* Set up Startcommand */
       WCommandMess.Command=WCMD_START_ACTIVE;              /* The magic word */
       WCommandMess.Param=WACFLG_FORBIDSCREENEVENTS;        /* Forbid Events on our Screen */
       WCommandMess.AppScreen=Demoscreen;                   /* Pointer to our Screen */
							    /* So we only get API-Events */
							    /* which occure on our screen */
							    /* and now on this screen no mouse */
							    /* emulation takes place */

       PutMsg(Wacom_data_Port,(struct Message *)&WCommandMess);

       /* Wait for Reply */
       WaitPort(Our_Port);

       /* Get response from driver */
       GetMsg(Our_Port);

       if(WCommandMess.Command==WCMD_OK)
       {
	Sigmask=WinSig|PortSig|SIGBREAKF_CTRL_C;   /* Signal Maks */

	/* Loop until it's over */
	while(cont)
	{
	 /* Wait for Window or CTRL-C Event */
	 Sigrcvd=Wait(Sigmask);

	 /* Check CTRL-C */
	 if(Sigrcvd & SIGBREAKF_CTRL_C)
	  cont=FALSE;

	 /* Check Message from Driver */
	 if(Sigrcvd & PortSig)
	 {
	  /* Print all inquired Data */
	  while(WMess=(struct WacomMSG *)GetMsg(Our_Port))
	  {
	   /* Copy Message */
	   /* Reply as soon as possible AND DON'T WRITE TO THE MESSAGE YOU GET */
	   CopyMem(WMess,&WDataMess,sizeof(struct WacomMSG));
	   ReplyMsg((struct Message *)WMess);     /* Reply immediately */

	   switch(WDataMess.Command)
	   {
	    case WCMD_MSG:           /* Message from Driver */
				     switch(WDataMess.Param)
				     {
				      case WACMSG_DRIVER_DEACTIVE:  /* Driver was deactivated */
								    SetWindowTitles(Win,"Driver is deactivated !",(UBYTE *)-1);
								    break;

				      case WACMSG_DRIVER_ACTIVE:    /* Driver was (re)activated */
								    SetWindowTitles(Win,"Driver has reactivated !",(UBYTE *)-1);
								    Delay(25);
								    SetWindowTitles(Win,"AvoidScreenDemo",(UBYTE *)-1);
								    break;

				      case WACMSG_DRIVER_QUIT:      /* Driver quits now !! */
								    /* Client application mustn't unregister ! */
								    printf("Driver quits right now !!\nDemo exits too.\n");
								    cont=FALSE;
								    Unregister_API=FALSE;
								    break;
				     }
				     break;

	    case WCMD_ERROR:         /* Error */
				     printf("Driver reported an Error !!\n");
				     break;

	    case WCMD_DATA_TRANS:    /* We got a datapackage from the tablet */
				     /* Now restore the old mouse and set the new mousepointer */
				     SetAPen(WinRP,oldpen);
				     WritePixel(WinRP,oldx,oldy);

				     /* Calculate mouseposition */
				     /* Do this every time, because the user can change */
				     /* the working area on the tablet !! */
				     x=(WORD)((float)((float)screenwidth/WDataMess.WacomInfo.Tablett_Max_X)*WDataMess.WacomInfo.Tablett_X);
				     y=(WORD)((float)((float)screenheight/WDataMess.WacomInfo.Tablett_Max_Y)*WDataMess.WacomInfo.Tablett_Y);

				     oldpen=ReadPixel(WinRP,x,y);
				     SetAPen(WinRP,2);
				     WritePixel(WinRP,x,y);
				     oldx=x;
				     oldy=y;

				     /* Paint with Button 1 down and clear with Button 2 */
				     switch(WDataMess.WacomInfo.Buttons)
				     {
				      case 1:  /* Paint */
					       oldpen=2;
					       break;

				      case 2:  /* Clear Painting */
					       /* This is a little bit crazy method */
					       Move(WinRP,0,0);
					       ClearScreen(WinRP);
					       RefreshWindowFrame(Win);
					       break;

				      default: break;
				     }
				     break;


	    default:                 /* Unspecified Package */
				     break;

	   }
	  }
	 }

	 /* Check Event from Window */
	 if(Sigrcvd & WinSig)
	 {
	  while(IMess=(struct IntuiMessage *)GetMsg(Win->UserPort))
	  {
	   class=IMess->Class;
	   ReplyMsg((struct Message *)IMess);  /* Send Msg back to Intuition */

	   switch(class)
	   {
	    case IDCMP_CLOSEWINDOW:     /* Somebody pushed the Closebutton */
					cont=FALSE;
					retval=0;
					break;

	    default:
					break;

	   }
	  }
	 }
	}
       }
       else
	printf("Error while attaching to active driver API !!\n");

       if(Unregister_API) /* Unregister only when Driver is still running */
       {
	/* Set up Quitcommand */
	WCommandMess.Command=WCMD_STOP_ACTIVE;               /* The magic word */
	WCommandMess.Param=WACFLG_ALLOWSCREENEVENTS;         /* Normal Eventhandling */
	WCommandMess.AppScreen=IntuitionBase->ActiveScreen;  /* Pointer to our Screen */

	/* Check if Port is still there */
	/* Don't forget this */
	if(FindPort(WACOM_PORT_NAME))
	{
	 PutMsg(Wacom_data_Port,(struct Message *)&WCommandMess);

	 /* Wait for Reply */
	 WaitPort(Our_Port);

	 /* Get response from driver */
	 GetMsg(Our_Port);

	 if(WCommandMess.Command != WCMD_OK)
	  printf("Error while unregistering from active driver API !!\n");
	}
	else
	 printf("Emergency Exit: Unable to Unregister from API !\n");
       }

       /* get rid of our port */
       DeleteMsgPort(Our_Port);
      }
      else
       printf("Unable to install a Message Port !!\n");

      /* Close Window */
      CloseWindow(Win);
     }
     else
      printf("Can't open Window !!\n");

     CloseScreen(Demoscreen);
    }
    else
     printf("Failed to open Custom Screen !!\n");

    /* Close Intution */
    CloseLibrary((struct Library *)IntuitionBase);
   }
   else
    printf("Unable to open intuition.library V37+!!!\n");

   /* Close Graphics */
   CloseLibrary((struct Library *)GfxBase);
  }
  else
   printf("Unable to open graphics.library V37+!!!\n");
 }
 else
  printf("Sorry... Can't find " WACOM_PORT_NAME "\n" );

 /* exit to Shell/WB */
 return(retval);
}

