/* ***********************************************************************

Programma ..... Esuom.c

Autore ........ Rob Einsenhuth (traduzione e revisione di L. Callegari)

Versione ...... 1.0i, Ottobre 1989

Funzione ...... Inverte gli effetti del mouse sul puntatore

Hardware ...... Amiga 500/2500, Kickstart & Workbench V1.2/1.3

Software ...... Lattice C V5.04 || Aztec C V3.6a

Sintassi ...... RUN Emouse (solo CLI)

Note .......... Traduzione ed adattamento di Luigi Callegari

     Lattice:   LC -O Esuom ---- ASM Hndstub.a
                BLINK from LIB:c.o+esuom.o+hndstub.o LIB lib:lc.lib nd sc
     Aztec:     CC +L Esuom ----- AS Hndstub.a
                LN esuom hndstub -lc32

*********************************************************************** */

#include <intuition/intuitionbase.h>
#include <devices/input.h>

#ifdef LATTICE
#include <proto/exec.h>
#include <proto/intuition.h>
#else
#include <functions.h>
#endif

#define PORTNAME "-=+RBE_esuoM+=-"

struct InputEvent *hndcode();    /* Funzione input handler */
void hndstub();                  /* Interfaccia Assembler */

struct Interrupt handlerptr; /* Per installazione dello handler */
struct MsgPort *inputport;   /* Porta messaggi per lo IO */
struct IOStdReq *inputreq;   /* Device di input per lo IO */
struct Message *m;           /* Per avere IntuiMessages*/
struct IntuitionBase *IntuitionBase;

struct Window *mywindow;     /* Nostra finestra, solo per terminare */

struct NewWindow mynewwindow =
{ 150, 50,     /* sinistra e alto */ 
  125, 10,     /* larghezza ed altezza */ 
  -1, -1,      /* penne */
  CLOSEWINDOW, /* IDCMP */
  WINDOWDEPTH | WINDOWCLOSE | WINDOWDRAG | SMART_REFRESH | NOCAREREFRESH |
  RMBTRAP,     /* flags */
  NULL, NULL,  /* gadget, checkmark */
  "esuoM",     /* titolo */
  NULL, NULL,  /* schermo, bitmap */
  0, 0, 0, 0,  /* dimensioni minima e massima */
  WBENCHSCREEN /* tipo schermo */
};

/* Questa funzione viene chiamata dal codice assembly hndstub() di
interfaccia, a sua volta chiamato ogni volta che si verifica un
evento di input. La routine hndstub() fornisce semplicemente la
interfaccia a livello assembly per il sistema di input di evento e
pone sullo stack i dati per il seguente handler, scritto in C.
********************************************************************/

struct InputEvent *hndcode(ie,data)
struct InputEvent *ie;    /* Evento di input effettivo da analizzare */
char *data;
{
  register struct InputEvent *e = ie;
 
  /* Dobbiamo modificare gli eventi RAWMOUSE con un codice NOBUTTON */
  do
  {

    if (e->ie_Class == IECLASS_RAWMOUSE && e->ie_Code == IECODE_NOBUTTON)
    {
      e->ie_X = - e->ie_X;  /* Se evento mouse, inverti spostamenti*/
      e->ie_Y = - e->ie_Y;
    }
    e = e -> ie_NextEvent;
  } while ( e != NULL );    /* Ripete se lista di eventi multipla */
  return(ie);               /* Passa eventi sotto la linea */
}

#ifdef LATTICE
     void MemCleanup() {}
#else
     _wb_parse() {}
     _cli_parse() {}
#endif

/* Se stiamo usando Aztec C facciamo trattare il codice assembly */

void _main()
{
  int waitmask, done;

  if (FindPort(PORTNAME) != NULL)  /* Guardiamo se già installato */
    _exit(99);                     /* altrimenti usciamo subito */

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

  inputport = CreatePort(PORTNAME,0);  /* Crea porta richiesta di IO */

  if (IntuitionBase== NULL || inputport==NULL) _exit(20);

  mywindow = OpenWindow(&mynewwindow); /* Apre finestra */

  if (mywindow == NULL) _exit (10); /* Termina se impossibile*/

  inputreq = CreateStdIO(inputport); /* Alloca richista di IO */

  if (inputreq == NULL) _exit(21); /* Esci se inapribile */

  if (OpenDevice("input.device",0,(struct IORequest *)inputreq,0) != NULL)
     _exit(22);                         /* Esci se inapribile */

  handlerptr.is_Code = hndstub;    /* Prepara struttura interrupt  */
  handlerptr.is_Data = NULL;       /* interfaccia assembly         */
  handlerptr.is_Node.ln_Pri = 100; /* priorità = 100 (max=127, Intui=50) */

  inputreq->io_Command = IND_ADDHANDLER;  /* Fissa requester di IO */
  inputreq->io_Data = (APTR)&handlerptr;
  DoIO((struct IORequest *)inputreq);     /* installa handler di input */

/* A questo punto abbiamo installato il nuovo input handler; attendiamo
perciò ora che arrivi un evento CLOSEWINDOW per terminare il programma */

  waitmask = ( 1L << mywindow -> UserPort -> mp_SigBit );

  done = FALSE;
  while (!done)             /* Continua ad attendere messaggi */
  {
    Wait(waitmask);         /* Attende messaggio IDCMP*/

    while ((m=GetMsg(mywindow->UserPort)) != NULL)  /* Guarda tutti */
    {
      if (((struct IntuiMessage *)m)->Class == CLOSEWINDOW)
        done = TRUE;        /*  Se CLOSEWINDOW ha terminato */
      ReplyMsg(m);          /*  risponiamo a tutti i messaggi*/
    }
  }

/* E' ora di terminare tutto, evento CLOSEWINDOW! */

  inputreq->io_Command = IND_REMHANDLER;    /* Inizia compressione      */
  DoIO((struct IORequest *)inputreq);       /* Rimuove handler di input */
  CloseDevice((struct IORequest *)inputreq);/* Chiude device d iinput   */
  DeleteStdIO(inputreq);                    /* Cancella request di IO   */
  DeletePort(inputport);                    /* Cancella messaggio di IO */
  CloseWindow(mywindow);                    /* Chiude finestra          */
  CloseLibrary((struct Library *)IntuitionBase);
  _exit(0L);                                /* Adios, Amigas!       */   
}
