/***********************************************/
/*                                             */
/*  demo.c - v. 2.0 - 8.88 - Antonio Ferrillo  */
/*                                             */
/*  programma dimostrativo dell'utilizzo delle */
/*  funzioni di gestione del console.device e  */
/*  dei menus residenti in libreria privata    */ 
/*                                             */
/*  versione Aztec v. 3.4  -  Lattice v. 3.10  */
/*                                             */
/***********************************************/ 

  #include <functions.h>    /* rimuovere questa 
linea se si usano i compilatori Lattice v. 3.XX*/

  #include <prifunc.h> /* vedere testo articolo*/ 

  #include <exec/types.h>
  #include <intuition/intuition.h>
  #include <graphics/rastport.h>
  #include <devices/input.h>

/* puntatore alla intuition library            */

  struct IntuitionBase *IntuitionBase;

/* definizione della funzione Window_Addr()
   residente in libreria privata che fornisce
   l'indirizzo della struct Window             */       

  struct  Window  *Window_Addr();

/* dichiarative per gestione dell'input.device */  

  struct   InputEvent     Mousev; 
                 /* struttura InputEvent       */
  struct   IOStdReq       *Req; 
              /* puntatore al blocco IORequest */
  struct   MsgPort        *Porto;
                     /* puntatore alla MsgPort */

/*  puntatori alle stringhe  per il display 
    del recovery Alert                         */ 

  char *cosa;	            
  char *al_mess[4];         
 
/* definizione e inizializzazione dell'array 
   che passeremo come argomento alla funzione 
   Menu_Set.
   Essendo possibile gestire max 5 tendine 
   ognuna delle quali puo' contenere  max 8 
   possibilita' di scelta (items) e nell'ambito 
   di ognuna di queste possono essere contenute 
   ancora 4 possibilita' (subitem) noi 
   definiremo una tabella quadridimensionale 
   contenente max 5 elementi-menu' (tendine) 
   ognuno dei quali contiene max 9 
   elementi_item (1 per l'header sulla 
   barra + 8 per gli items) ognuno dei quali 
   contiene max 5 elementi-stringhe
   (1 per l'item + 4 per i subitems associati) 
   ognuno dei quali contiene max 12 elementi 
   carattere (Il primo elemento e' il carattere 
   di comando da tastiera in alternativa al 
   mouse : se non lo si vuol usare inserire
   uno spazio, seguono 10 caratteri per il 
   testo + '\0' aggiunto dal compilatore).
   Naturalmente inizializzeremo solo gli 
   elementi che ci servono ma e' necessario, 
   per il buon funzionamento della routine 
   Menu_Set, dimensionare l'array come indicato.                                                 
*/
  char menu[5][9][5][12] =
  {
       {
             {"PRIMI "},
             {" PENNE","BBOLOGNESE","RAL RAGU'",
                      "AARRABBIATA","ZZINGARA"}, 
             {" SPAGHETTI","PPOMODORO",
                                   "V VONGOLE"},
             {" RISOTTO","MMILANESE",
                                  " PESCATORA"},
             {" MINESTRE","FAI FAGIOLI",
                                    " VERDURE"},
	     {"CCONSOMME'"}
       },
       {
             {"SECONDI"},
             {" CARNE"," BOLLITA"," ALLA BRACE"},
             {" FIORENTINA"},
             {" PESCE"," AL FORNO"," ALLA BRACE"},
             {" UOVA","TTEGAMINO","SSODE"}
       },
       {
             {"FORMAGGI"},
             {"GGRANA"},
             {" GORGONZOLA"},
             {" FRANCESI"," CAMEMBERT",
                                     " CAPRICE"},
	     {" PROVOLONE"},
	     {"EEDAM"},
             {" MOZZARELLA"},
             {" FONTINA"},
             {" STRACCHINO"} 
       },
       {
             {"DOLCI"},
             {" CASSATA"},
             {" TORTE"," CIOCCOLATO",
                                  " ST.HONORE'"},
             {" PASTIERA"},
	     {" CROSTATA"," DI MELE",
                                   " DI PESCHE"}
       },
       {
             {"FRUTTA"},
             {" ESOTICA","NANANAS"," MANGO",
                            " PAPAYA","JBANANA"},
             {" NOSTRANA"," PERE"," PESCHE"},
             {"KMACEDONIA"}
       }

  };

  void Call_Al();    
      /*  arrangiamento messaggio per l'Alert  */
  void Alert_Dis();   
      /*  display recovery Alert   */
  void OpenIntuiLib();
      /*  apertura intuition.library  */
  void OpenScr();
      /*  apertura schermo  */
  void OpenWin();
      /*  apertura finestra  */
  void ConsDevDemo();
      /*  dimostrazione console.device  */ 
  void MenusDemo();
      /*  dimostrazione menus  */
  void MenuMouse();
      /*  emulazione movimenti mouse  */
  void EndProg();
      /*  operazioni di chiusura  */            
  void GestMessaggi();
      /*  intercettazione messaggi IDCMPs */

  int indscr,indwin,indcondev,indinpdev,indmenu;

/*    corpo principale del programma      */  
  void
  main()
  {
    OpenIntuiLib();
    OpenScr();
    OpenWin();
    ConsDevDemo();
    MenusDemo();
  }


/* routine elaborative richiamate nel 
   corpo principale, quelle di  apertura 
   comprendono il controllo di successo 
   dell'operazione con il display di un 
   Alert di tipo 'RECOVERY' e uscita 
   dall'elaborazione in caso di fallimento     */

/* routine apertura della libreria delle routines 
   per la gestione di Intuition residenti in ROM 
   richiamate durante l'esecuzione             */

    void	
    OpenIntuiLib()
    {
      IntuitionBase =  (struct IntuitionBase *)
            OpenLibrary("intuition.library", 0L);
        if (IntuitionBase == NULL)
        {
          cosa="intuition.library";
          Call_Al();
          EndProg(); 	
        } 
    }

/* apertura dello schermo  mediante il richiamo
   della routine Screen_Open() catalogata in 
   libreria privata                          */

    void
    OpenScr()
    {
       indscr = Screen_Open 
 (1,"DEMO console.device - menus",0,256,0,1,2,3); 
          if (indscr == 0)         
          {
            cosa="SCHERMO";
            Call_Al();
            EndProg();
          }
    } 


/* apertura finestra                         */

    void
    OpenWin()
    {
        indwin =  Window_Open
 (1,"DEMO console.device",0,10,640,246,1,0,1);
           if (indwin == 0)
           {
             cosa="FINESTRA";
             Call_Al();
             EndProg();      
           }
    } 

/*  dimostrazione console.device             */    

    void
    ConsDevDemo()
    {
      int colbg = 7;
      int linea = 1;
      int colonna = 1;
      int nchar;
      char buflet[78];
      char *stringa;

/*  apertura console.device         */   

      indcondev = Con_Open(1);  
      if (indcondev == 0)
           {
             cosa="console.device";
             Call_Al();
             EndProg();
           }
 
/* reset finestra col colore colbg  */    

      while(colbg)           
      {
        Delay(50L);
        Con_Clescr(colbg);
        colbg--;
      }

/* posizionamento cursore e reset finestra 
   da cursore col colore colbg    */
   
      for ( linea=2; linea < 28; linea++) 
      {        
        Delay(30L);
        colbg = linea % 7;
        Con_Poscur(linea,colonna);
        Con_Clecur(colbg);
      }
   
/* posizionamento cursore e reset linea 
   da cursore in poi      */ 

     for (colonna = 1 ; colonna < 79; colonna++)
      {                              
        Delay(10L);
        colbg = colonna % 7;
        Con_Poscur(linea,colonna);
        Con_Clelin(colbg);
      }   

/* scrittura di un testo e sparizione cursore  */

     
      Con_Write(29,1,3,2,3,"SPARIZIONE CURSORE ");
      Delay(50L);     
      Con_Cursoff();  

/* scrittura di un testo e apparizione cursore  */

      Delay(100L);
    Con_Write(29,1,3,2,3,"RIAPPARIZIONE CURSORE");
      Con_Curson();

/* scrittura di un testo e lettura di una 
   stringa di max 10 caratteri */
     
      Delay(100L);
      Con_Write(15,1,0,1,2,
    "digitare max 10 caratteri e premere return");
      nchar =  Con_Read(15,50,1,4,5,buflet,10);

/* scrittura stringa digitata e numero dei 
   caratteri digitati    */

      stringa =
 "stringa digitata :           n. caratteri :   ";
      stringa[44] = nchar / 10 | 48;
      stringa[45] = nchar % 10 | 48;
      nchar = 0;
  while(stringa[19+nchar]=buflet[nchar]) nchar++;  
      stringa[19+nchar] = ' ';
      Con_Write(17,1,0,2,3,stringa);

/* scroll in alto                 */

      for (nchar=0; nchar < 29; nchar++)
      {
        Delay(10L);
        Con_Scrollup();
        Con_Write(30,1,7,2,6,"---SCROLL  UP---");
      }

/* scroll in basso                 */

      for (nchar=0; nchar < 36; nchar++)
      {
        Delay(10L);
        Con_Scrolldown();
        Con_Write(1,1,7,2,5,"--SCROLL  DOWN--");
      }
  }

/*   dimostrazione gestione menus          */
 
    void
    MenusDemo()
    {

/* cambio del titolo della finestra 
   il terzo argomento : -1L  fa lasciare 
   inalterato il titolo dello schermo     */  

  SetWindowTitles
    (Window_Addr(1),"DEMO GESTIONE menus",-1L);

/* apertura input device per emulare i 
   movimenti del mouse                */

   Porto  = (struct MsgPort *)CreatePort (0L,0L);
   if (Porto == NULL)
   {
     cosa="Porto input.device";
     Call_Al();
     EndProg();
   }

   Req = (struct IOStdReq *)CreateStdIO(Porto);
   if (Req == NULL)
   {
     cosa="IORequest input.device";
     Call_Al();
     EndProg();
   }

   if(OpenDevice("input.device",0L,Req,0L) != 0L)
   {
    indinpdev = 0;
    cosa="input.device";
    Call_Al();
    EndProg();      
   }

   Req -> io_Command = IND_WRITEEVENT;
   Req -> io_Flags   = 0;
   Req -> io_Length  = sizeof(struct InputEvent);
   Req -> io_Data    = (APTR) &Mousev;

/* aggancio menus alla finestra               */

   indmenu = Menu_Set(1,1,menu);
   if (indmenu == 0)         
   {
     cosa="MENUS";
     Call_Al();
     EndProg();
   }

/* emulazione selezione menus                */

   MenuMouse(1,3,1);    /* selezione menu    */
   GestMessaggi();      /* cattura messaggio 
                            menu selezionato */
   MenuMouse(1,3,1);    /* visualizzazione 
                    stesso menu disattivato  */

   MenuMouse(2,2,0);
   GestMessaggi();
   MenuMouse(2,2,0);

   MenuMouse(5,1,4);
   GestMessaggi();
   MenuMouse(5,1,4);
  
   MenuMouse(3,3,2);
   GestMessaggi();
   MenuMouse(3,3,2);
  
   MenuMouse(4,4,1);
   GestMessaggi();
   MenuMouse(4,4,1);

/*  emulazione chiusura finestra            */

   Mousev.ie_Class = IECLASS_RAWMOUSE;
   Mousev.ie_Code = IECODE_NOBUTTON ;
   Mousev.ie_Y   = -524;
   Mousev.ie_X   = -704;
   DoIO (Req); 
     
   Mousev.ie_Y   = 30;
   Mousev.ie_X   = 10;
   DoIO (Req);

   Mousev.ie_Y   = 0;
   Mousev.ie_X   = 0; 
   Mousev.ie_Code = IECODE_LBUTTON;
   DoIO(Req);   
   Delay(150L); 

   Mousev.ie_Code=IECODE_LBUTTON+IECODE_UP_PREFIX;
   DoIO(Req);
   GestMessaggi();
  }

/* intercettazione dei messaggi riguardanti i 
   movimenti del mouse emulati con l'input device,
   e ricevuti tramite IDCMPs di Intuition      */ 
 
   void
   GestMessaggi()
   {

/* definizione campi per la gestione dei 
   messaggi ricevuti da Intuition mediante IDCMPs.
   ULONG e USHORT sono ridefinizioni di tipo di 
   dato contenute nella <exec.types.h>         */

  struct IntuiMessage *messaggio;
  ULONG TipoMessaggio;  
  USHORT numes;         

/* definizione comodi di lavoro               */
    
      int nmenu,nitem,nsub,k;
      char *strmen;
      cosa =
 "menu selezionato :                          "; 
      strmen = cosa;
      cosa += 19;

 Wait(1L << Window_Addr(1)->UserPort->mp_SigBit);

      while ( messaggio = (struct IntuiMessage *)
                GetMsg(Window_Addr(1)->UserPort))
      {
        TipoMessaggio = messaggio->Class;
        numes = messaggio->Code;
        ReplyMsg(messaggio);
        switch (TipoMessaggio)
        {
          case CLOSEWINDOW :  EndProg();
          case MENUPICK    : 
                    if (numes == MENUNULL) break; 
                    nmenu = MENUNUM(numes);
                    nitem = ITEMNUM(numes);
                    nsub = SUBNUM(numes); 
       k = 0;
       while(*++cosa = menu[nmenu][0][0][k]) k++;                   
       *cosa = ' ';
       k=1;           
 while(*++cosa = menu[nmenu][nitem+1][0][k]) k++;
       if (nsub != NOITEM)
        {
          *cosa = ' ';
          k= 1;                   
 while
 (*++cosa = menu[nmenu][nitem+1][nsub+1][k]) k++;                   
        }
              
       Con_Write(15,1,0,0,1,strmen);
       Con_Scrollup();

       Menu_OnOff(1,0,nmenu+1,nitem+1,nsub+1);
       break;
   
        }   /* switch */
      }  /* while */
   }   /* GestMessaggi() */
      
/* routine simulazione selezione menus      */

  void 
  MenuMouse(men,it,sub)
  int men,it,sub;
  {
   int mx,my;

/* azzeramento posizione del mouse  */

   Mousev.ie_NextEvent   = NULL;            
   Mousev.ie_Class       = IECLASS_RAWMOUSE;
   Mousev.ie_TimeStamp.tv_secs  = 0;
   Mousev.ie_TimeStamp.tv_micro = 0;
   Mousev.ie_Code        = IECODE_RBUTTON;
   Mousev.ie_Qualifier=IEQUALIFIER_RELATIVEMOUSE;
   Mousev.ie_Y   = -524;
   Mousev.ie_X   = -704;
   DoIO (Req);     

   Mousev.ie_Y  = 5;
   DoIO(Req);

/* posizionamento sul menu  */

   Mousev.ie_Y   = 0;
   Mousev.ie_X   = 1;
   for(mx = 0; mx < (men * 100 - 50); mx++)
                                     DoIO (Req); 

/* posizionamento sull'item  */
 
   Mousev.ie_Y   = 2;
   Mousev.ie_X   = 0;
   for(my = 0; my < (it * 10 + 5); my++)
                     { Delay(1L); DoIO (Req); }

/* posizionamento sul subitem  */

   mx = 0;
   my = 0;

   Mousev.ie_Y   = 0;
   Mousev.ie_X   = 1;
   while(sub != 0 && mx < 120) {mx++; DoIO(Req);}

   Mousev.ie_Y   = 2;
   Mousev.ie_X   = 0;
   while(sub != 0 && my < (sub * 10 - 10))
                { Delay(1L);  my++; DoIO (Req); }

   Delay(100L);
   Mousev.ie_Code=IECODE_RBUTTON+IECODE_UP_PREFIX;
   DoIO (Req);

  }


/* routine di arrangiamento prima riga di 
   messaggio dell'Alert             */       
   void
   Call_Al()
   {
   int k=0;
   al_mess[0] =
        "ERRORE IN APERTURA                    ";
   al_mess[1] =
        "PROSECUZIONE IMPOSSIBILE";
   al_mess[2] =
        "CLICKARE SU UNO DEI PULSANTI DEL MOUSE";
   while(*(al_mess[0]+19+k) = *cosa++) k++;
   al_mess[3] = '\0';
   Alert_Dis(al_mess);
   }

/* routine di arrangiamento degli argomenti 
   richiesti dalla funzione di Intuition  
   DisplayAlert()                            */
 
   void
   Alert_Dis(testo)
     char  *testo[];
   {
   short colonna = 84;
   char dispmess[260];
   char *mess, *col;
   int n;
   long tipo = RECOVERY_ALERT;
   mess = dispmess;
   col = &colonna;
      for ( n=0; n<4; n++ )
      {
      if(*testo[n] == '\0') break;
      *mess = *col;
      *++mess =*(col+1);
      *++mess = (char)3+(9*(n+1));
      while(*++mess = *testo[n]++); 
      *++mess = (char)1;
      mess++;
      }
   *mess = '\0';
   DisplayAlert(tipo,dispmess,50L);
   }

  void
  EndProg()
  {
    if (indmenu) Menu_Reset(1);
    if (indinpdev) CloseDevice(Req);
    if (Req)  DeleteStdIO(Req);
    if (Porto) DeletePort(Porto);
    if (indcondev) Con_Close();
    if (indwin) Window_Close(1);
    if (indscr) Screen_Close(1);
    if (IntuitionBase)CloseLibrary(IntuitionBase);
    exit(TRUE);
  }

