/***************************************************************************/
/*                                                                         */
/*	      cons.c  -  v. 1.0  - 8.88  -  Antonio Ferrillo               */
/*                                                                         */
/*               funzioni di gestione del console device                   */
/*                                                                         */ 
/*               versione Aztec 3.4  -   Lattice 3.10                      */
/*                                                                         */
/***************************************************************************/ 

  #include <functions.h>   /* rimuovere questa linea se si usano 
                             i compilatori Lattice V. 3.xx   */
  #include <exec/types.h>
  #include <intuition/intuition.h> 

/* sequenze di controllo                                                   */

  UBYTE escdata[] = {
                      0x9b, 'J', '\0', /* cancellazione fino a fine display */
                      0x9b, 'K', '\0', /* cancellazione fino a fine linea */
		      0x9b, 'S', '\0',           /* scroll up */
		      0x9b, 'T', '\0',           /* scroll down */
		      0x9b, ' ', 'p', '\0',       /* cursor on */
		      0x9b, '0', ' ', 'p', '\0',   /* cursor off */
                      0x0c, '\0'                  /* clear schermo  */
                    };

  UBYTE rigdata[]={ 0x9B,'0','0',';','0','0',0x48,'\0' };/* riga e colonna */
  UBYTE stildata[]={ 0x9B,'0',';','3','0',';','4','0',0x6D,'\0' }; /* stile
                                                                  e colore */             
  #define ERASEEODSTRING 		&escdata[0] 
  #define ERASEEOLSTRING 		&escdata[3] 
  #define SCROLLUPSTRING 		&escdata[6] 
  #define SCROLLDOWNSTRING      	&escdata[9]
  #define CURSONSTRING 		        &escdata[12] 
  #define CURSOFFSTRING 		&escdata[16]
  #define CLEARSTRING    		&escdata[21] 
  #define RIGACOL                       &rigdata[0]
  #define STILCOL                       &stildata[0]

/* definizione macro richiamate in seguito                                 */  

  #define CLEARSCREEN(r)		ConPutStr(r,CLEARSTRING)
  #define SCROLLDOWN(r) 		ConPutStr(r,SCROLLDOWNSTRING)
  #define ERASEEOD(r) 	        	ConPutStr(r,ERASEEODSTRING)
  #define ERASEEOL(r) 		        ConPutStr(r,ERASEEOLSTRING)
  #define SCROLLUP(r)   		ConPutStr(r,SCROLLUPSTRING)
  #define CURSORON(r) 	        	ConPutStr(r,CURSONSTRING)
  #define CURSOROFF(r) 		        ConPutStr(r,CURSOFFSTRING)
  #define RIGACOLONNA(r)                ConPutStr(r,RIGACOL)
  #define STILCOLOR(r)                  ConPutStr(r,STILCOL) 

  struct IOStdReq *consoleWriteMsg; /*  I/O request block scrittura   */
  struct MsgPort *consoleWritePort; /*porto di ricezione messaggi scrittura*/	
  struct IOStdReq *consoleReadMsg;  /*  I/O request block lettura     */
  struct MsgPort *consoleReadPort;  /* porto di ricezione messaggi lettura */	

/*   tabella caratteri consentiti                                          */

  UBYTE key[100] = {
                    'a','b','c','d','e','f','g','h','i','j','k',
                    'l','m','n','o','p','q','r','s','t','u','v',
                    'w','x','y','z','A','B','C','D','E','F','G',
                    'H','I','J','K','L','M','N','O','P','Q','R',
                    'S','T','U','V','W','X','Y','Z',' ','1','2',
                    '3','4','5','6','7','8','9','0',',','.',';',
                    ':','-','+','*','/','=','_','<','>','(',')',
                    '[',']','{','}','#','£','$','%','&','!','?',
                    '|','\\','"','@','§','\'','ì','è','é','ò',
                    'à','ù'
                   };

  void Con_Poscur();
  void ConSticol();
  void ConPutStr();

/*---------------------------------------------------------------------------
|  int
|  Con_Open(wn)
| 
|     FUNZIONE  : apertura di console device.
| 
|     ARGOMENTI : int wn;      - (valore = da 1 a 4)  numero della
|                                finestra cui associare il device.
|
|     RITORNO   : TRUE se l'apertura e' andata a buon fine,
|                 FALSE se e' sopravvenuto un errore.
| 
|     NOTE      : ricordarsi di chiudere il device a fine
|                 lavoro mediante la Con_Close.
|__________________________________________________________________________*/

  int
  Con_Open(wn)
  int wn;
  {
   int error;
   struct  Window   *Window_Addr(), *win_ptr;

   if(wn < 1 || wn > 4) return(FALSE);

   consoleWritePort = (struct MsgPort *)CreatePort("my.con.write",0L);
   if(consoleWritePort == 0)  return (FALSE);

   consoleWriteMsg =  (struct IOStdReq *)CreateStdIO(consoleWritePort);
   if(consoleWriteMsg == 0)  return(FALSE);

   consoleReadPort = (struct MsgPort *)CreatePort("my.con.read",0L);
   if(consoleReadPort == 0)  return(FALSE);

   consoleReadMsg = (struct IOStdReq *) CreateStdIO(consoleReadPort);
   if(consoleReadMsg == 0) return(FALSE);

   win_ptr = Window_Addr(wn);

   consoleWriteMsg->io_Data = (APTR) win_ptr;
   consoleWriteMsg->io_Length = sizeof(*win_ptr);
 
   error = OpenDevice("console.device", 0L, consoleWriteMsg, 0L);
   if(error != 0)  return(FALSE);

/* nel blocco di lettura vengono copiati alcuni campi settati dalla
   OpenDevice nel blocco di scrittura, in modo tale che sia l'input che 
   l'output vengano diretti sullo stesso  device.                          */   
 
   consoleReadMsg->io_Device = consoleWriteMsg->io_Device;
   consoleReadMsg->io_Unit  = consoleWriteMsg->io_Unit;

   return(TRUE);
  }


/*---------------------------------------------------------------------------
|  void
|  Con_Close()
| 
|     FUNZIONE  : effettua la Close del device.
|__________________________________________________________________________*/

  void
  Con_Close()
  {
   CloseDevice(consoleWriteMsg);
   DeleteStdIO(consoleReadMsg);
   DeletePort(consoleReadPort);
   DeleteStdIO(consoleWriteMsg);
   DeletePort(consoleWritePort);
  }


/*---------------------------------------------------------------------------
|  void
|  Con_Clescr(colbg)
| 
|     FUNZIONE  : abblenca la finestra e la setta col colore colbg.
| 
|     ARGOMENTI : int colbg;   - (valore = da 0 a 7) codice colore di
|                                 background. 
|__________________________________________________________________________*/

  void
  Con_Clescr(colbg)
  int colbg;
  {
   ConSticol(0,colbg,colbg);
   CLEARSCREEN(consoleWriteMsg);
  }
	

/*---------------------------------------------------------------------------
|  void
|  Con_Clecur(colbg)
| 
|     FUNZIONE  : abblenca la finestra dalla posizione del cursore
|                 e la setta col colore colbg.
| 
|     ARGOMENTI : int colbg;   - (valore = da 0 a 7)  codice colore di
|                                 background. 
|__________________________________________________________________________*/

  void
  Con_Clecur(colbg)
  int colbg;
  {
   ConSticol(0,colbg,colbg);
   ERASEEOD(consoleWriteMsg);
  }


/*---------------------------------------------------------------------------
|  void
|  Con_Clelin(colbg)
| 
|     FUNZIONE  : abblenca la linea dalla posizione del cursore
|                 e la setta col colore colbg.
| 
|     ARGOMENTI : int colbg;   - (valore = da 0 a 7)  codice colore di
|                                 background. 
|__________________________________________________________________________*/

  void
  Con_Clelin(colbg)
  int colbg;
  {
   ConSticol(0,colbg,colbg);
   ERASEEOL(consoleWriteMsg); 
  }


/*---------------------------------------------------------------------------
|  void
|  Con_Scrollup()
| 
|     FUNZIONE  : effettua lo scroll in alto di una linea.
|__________________________________________________________________________*/

  void
  Con_Scrollup()
  {
   SCROLLUP(consoleWriteMsg);
  }


/*---------------------------------------------------------------------------
|  void
|  Con_Scrolldown()
| 
|     FUNZIONE  : effettua lo scroll in basso di una linea.
|__________________________________________________________________________*/

  void
  Con_Scrolldown()
  {
   SCROLLDOWN(consoleWriteMsg);
  }


/*---------------------------------------------------------------------------
|  void
|  Con_Curson()
| 
|     FUNZIONE  : fa apparire il cursore.
|__________________________________________________________________________*/

  void
  Con_Curson()
  {
   CURSORON(consoleWriteMsg);
  }


/*---------------------------------------------------------------------------
|  void
|  Con_Cursoff()
| 
|     FUNZIONE  : fa sparire il cursore.
|__________________________________________________________________________*/

  void
  Con_Cursoff()
  {
   CURSOROFF(consoleWriteMsg);
  }


/*---------------------------------------------------------------------------
|  void
|  Con_Write(riga,col,stile,colfg,colbg,testo)
| 
|     FUNZIONE  : scrive nella finestra una stringa NULL-terminata.
| 
|     ARGOMENTI : int riga;  - (valore > 0  dipendente dalla risoluzione 
|                              dello schermo, dalla Font prescelta,
|                              dalle dimensioni della finestra)
|                              numero di riga sulla quale va visualizzato il
|                              testo.
|                 
|                 int col;   - (valore > 0  dipendente dalla risoluzione
|                              dello schermo, dalla Font prescelta,
|                              dalle dimensioni della finestra) 
|                              numero della colonna a partire dalla quale va
|                              visualizzato il testo.
|
|                 int stile; - stile di scrittura, valore :
|                              0 = plain,  1 = boldface,
|                              3 = italic, 4 = underscore, 7 = inverse
|                                                    
|                 int colfg; - (valore da 0 a 7) colore di foreground.
|
|                 int colbg; - (valore da 0 a 7)colore di background
|           
|                 char *testo- stringa da visualizzare terminata con '\0'.
|__________________________________________________________________________*/

  void
  Con_Write(riga,col,stile,colfg,colbg,testo)
  int riga;
  int col;
  int stile;
  int colfg;
  int colbg;
  char  *testo;
  {
   Con_Poscur(riga,col);
   ConSticol(stile,colfg,colbg);
   ConPutStr(consoleWriteMsg,testo);
  }


/*---------------------------------------------------------------------------
|  int
|  Con_Read(riga,col,stile,colfg,colbg,area,len)
| 
|     FUNZIONE  : accetta da tastiera e visualizza nella finestra una
|                 stringa di lunghezza massima = len terminata col tasto
|                 'return',ritorna in area la stringa digitata.  
| 
|     ARGOMENTI : int riga;  - (valore > 0 dipendente dalla risoluzione
|                              dello schermo, dalla Font prescelta,
|                              dalle dimensioni della finestra)
|                              numero di riga sulla quale va visualizzato il
|                              testo digitato.
|                 
|                 int col;   - (valore > 0  dipendente dalla risoluzione 
|                              dello schermo, dalla Font prescelta,
|                              dalle dimensioni della finestra)  
|                              numero della colonna a partire dalla quale va
|                              va visualizzato il testo digitato.
|
|                 int stile; - stile di scrittura, valore :
|                              0 = plain,  1 = boldface,
|                              3 = italic, 4 = underscore, 7 = inverse
|                                                    
|                 int colfg; - (valore da 0 a 7) colore di foreground.
|
|                 int colbg; - (valore da 0 a 7) colore di background.
|
|                 char *area - buffer di destinazione della stringa digitata
|                              di dimensioni = a len + 1, viene terminato con
|                              il carattere '\0'. 
|
|                 int len    - numero massimo di caratteri da accettare. 
| 
|     RITORNO   : se l'operazione e' andata a buon fine :
|                 il numero dei caratteri digitati ed, in area, la stringa 
|                 digitata. 
|                 FALSE se e' sopravvenuto un errore.
|__________________________________________________________________________*/

  int
  Con_Read(riga,col,stile,colfg,colbg,area,len)
  int riga;
  int col;
  int stile;
  int colfg;
  int colbg;
  UBYTE *area;
  int len;
  {
   UBYTE ConGetChar();
   UBYTE car; 
   int nlet;
   int nkey;
   char blanks[80];

   switch (stile)
    {
     case 0 : 
     case 1 :
     case 3 :
     case 4 :
     case 7 : break;
     default : return (FALSE);
    }
 
   if (colfg < 0 || colfg > 7) return (FALSE);   
   if (colbg < 0 || colbg > 7) return (FALSE);
   Con_Poscur(riga,col);
   ConSticol(stile,colfg,colbg);
  
   for(nlet = 0; nlet < len; blanks[nlet] = ' ',nlet++);
   blanks[nlet] = '\0';
   ConPutStr(consoleWriteMsg,blanks);
   Con_Poscur(riga,col);  

   for(nlet = 0;; nlet++)
   {
     car= ConGetChar(consoleReadPort,consoleReadMsg);
     if (car == '\r') break;  /* se e' stato premuto il tasto 'return'   */
    
     if (car == '\b')   /* se e' stato premuto il tasto 'backspace' */                                              
     {
       if (nlet <= 0) { DisplayBeep(NULL); nlet--;  continue; } 
       nlet -= 2 ;
       ConPutStr(consoleWriteMsg,&car);
       continue;
     }
    
     if (nlet >= len)  /* se e' stato raggiunto il massimo dei caratteri */
          { DisplayBeep(NULL);  nlet-- ; continue; }
 
     for(nkey = 0; nkey < 100; nkey++)  /* controllo caratteri ammessi */ 
          if(car == key[nkey]) goto bypass; 
    
     DisplayBeep(NULL);  /* lampeggia lo schermo per segnalare errore */
     nlet-- ; 
     continue; 

     bypass: 
     ConPutStr(consoleWriteMsg,&car);  /* scrittura carattere digitato  */
     area[nlet] = car;  /* carattere digitato in buffer */
   } 
   area[nlet] = '\0';  /* carattere terminatore a fine stringa */
   return(nlet);
  }


/*---------------------------------------------------------------------------
|  void
|  Con_Poscur(riga,colonna)
| 
|     FUNZIONE  : posiziona il cursore a riga e colonna.
| 
|     ARGOMENTI : int riga;  - (valore > 0  dipendente dalla risoluzione 
|                              dello schermo, dalla Font prescelta,
|                              dalle dimensioni della finestra)
|                              numero di riga sulla quale va posizionato il 
|                              cursore.
|                 
|                 int colonna; - (valore > 0 dipendente dalla risoluzione
|                               dello schermo, dalla Font prescelta,
|                               dalle dimensioni della finestra)
|                               numero della colonna sulla quale va 
|                               posizionato il cursore.
|__________________________________________________________________________*/

  void
  Con_Poscur(riga,colonna)
  int riga;
  int colonna;
  {
   rigdata[1] =  riga / 10 | 48;
   rigdata[2] =  riga % 10 | 48;
   rigdata[4] =  colonna / 10 | 48;
   rigdata[5] =  colonna % 10 | 48;
   RIGACOLONNA(consoleWriteMsg);
  }


/*...........................................................................
|  void
|  ConSticol(stile,colfg,colbg)
|     FUNZIONE  : determina stile e colore prima di una visualizzazione.
|     ARGOMENTI : int stile; - stile di scrittura, valore :
|                              0 = plain,  1 = boldface,
|                              3 = italic, 4 = underscore, 7 = inverse
|                 int colfg; - (valore da 0 a 7) colore di foreground.
|                 int colbg; - (valore da 0 a 7) colore di background.
|     NOTE : destinata ad utilizzo interno al sorgente. 
|..........................................................................*/

  void
  ConSticol(stile,colfg,colbg)
  int stile;
  int colfg;
  int colbg;
  {	
   stildata[1] = stile | 48;
   stildata[4] = colfg | 48;
   stildata[7] = colbg | 48;
   STILCOLOR(consoleWriteMsg);
  }


/*...........................................................................
|  void
|  ConPutStr(request,string)
|     FUNZIONE  : scrive una stringa NULL-terminata.
|     ARGOMENTI : struct IOStdReq *request; - I/O request block.
|                 char *string; - stringa NULL-terminata.
|     NOTE : destinata ad utilizzo interno al sorgente.
|..........................................................................*/

  void
  ConPutStr(request,string)
  struct IOStdReq *request;
  char *string;
  {
   request->io_Command = CMD_WRITE;
   request->io_Data = (APTR)string;
   request->io_Length = -1; 
   DoIO(request);
  }
	

/*...........................................................................
|  UBYTE
|  ConGetChar(consolePort,request)
|     FUNZIONE  : accetta da tastiera un carattere.
|     ARGOMENTI : struct MsgPort *consolePort; - struttura porto di arrivo
|                                                dei messaggi del device.
|                 struct IOStdReq *request; - I/O request block.
|     RITORNO   : carattere digitato.
|     NOTE : destinata ad utilizzo interno al sorgente. 
|..........................................................................*/

  UBYTE
  ConGetChar(consolePort,request)
  struct IOStdReq *request; 
  struct MsgPort *consolePort;   
  {
   UBYTE temp[5];
   request->io_Command = CMD_READ;
   request->io_Data = (APTR)&temp;
   request->io_Length = 5;  
   SendIO(request);
   while((GetMsg(consolePort) == NULL)) WaitPort(consolePort);
   return(temp[0]);
  }

