#include <exec/types.h>
#include <exec/libraries.h>
#include <exec/ports.h>
#include <intuition/intuition.h>
#include <libraries/gadtools.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "XCMD.h"
#include "XCMDTools.h"

#define forever for(;;)

/*
*     Les principales variables :
*/
struct GadgetList *glist         = NULL;
struct Window     *window        = NULL;
struct Screen     *screen_lock   = NULL;
void              *vi            = NULL;
struct MsgPort    *port          = NULL;
BPTR              dir_lock;
struct Library    *GadToolsBase  = NULL;
struct TextAttr   Topaz80        = { "topaz.font",8,0,0 };
char              ligne[256];
struct Panel
  {
  BOOL pa_Set;
  char pa_Texte[10];
  char pa_Commande[256];
  };
struct Panel      Panel[25];
int               PanelIX = 0;


/*
*
*       prototypes des fonctions utilisées
*
*/

void Load(void);
void InterpreterLigne(void);
BOOL InitPanel(void);


/*
*       void InterpreterLigne(void)
*
*       Interprète la variable _ligne_ et associe le texte
*       et la commande à un gadget du panel.
*
*/
void InterpreterLigne()
  {
  int i = 0;
  while((ligne[i] == ' ') && (ligne[i]))
    i++;
  if(ligne[i])
    {
    int j = 0;
    while((ligne[i] != ';') && (ligne[i]))
      {
      if(j<9)
        Panel[PanelIX].pa_Texte[j] = ligne[i];
      else if(j==9)
        Panel[PanelIX].pa_Texte[j] = '\0';
      i++;
      j++;
      }
    if((ligne[i] == ';') && (j<9))
      Panel[PanelIX].pa_Texte[j] = '\0';
    if(ligne[i])
      {
      i++;
      while((ligne[i] == ' ') && (ligne[i]))
        i++;
      if(ligne[i])
        {
        int k = 0;
        while(ligne[i])
          {
          Panel[PanelIX].pa_Commande[k] = ligne[i];
          i++; k++;
          }
        Panel[PanelIX].pa_Commande[k] = ligne[i];
        Panel[PanelIX].pa_Set = TRUE;
        PanelIX++;
        }
      }
    }
  }




/*
*
*       void Load(void)
*
*       Charge le fichier "panel.config" pour définir les
*       commandes associés au gadget. Chaque ligne est lue
*       dans la variable _ligne_ qui est ensuite interprétée
*
*/
void Load()
  {
  FILE *fp;
  int i,c;
  for(i = 0; i<25; i++)
    Panel[i].pa_Set = FALSE;
  fp = fopen("panel.config","r");
  if(fp)
    {
    forever         /* lecture jusqu'à EOF ou erreur */
      {
      i = 0;
      forever
        {
        c = fgetc(fp);
        if((c == EOF) || (c == '\n') || (i == 255))
          {
          ligne[i] = '\0';
          break;
          }
        else
          {
          ligne[i] = c;
          i++;
          }
        }
      if(strlen(ligne) && (ligne[0] != '#'))
        InterpreterLigne();
      if ((c == EOF) || (PanelIX == 25)) break;
      }
    fclose(fp);
    }
  }



/*
*       InitPanel()
*
*       Cette routine initialise le Panel, en lisant
*       un fichier de configuration "panel.config".
*       Une fenêtre est ouverte avec tous les gadgets
*       nécessaires. Retourne TRUE si tout est OK,
*       FALSE sinon.
*
*/
BOOL InitPanel()
  {
  vi = GetVisualInfo(screen_lock, TAG_DONE);
  if(!vi)
    {
    puts("Impossible d'avoir les visual infos");
    return(FALSE);
    }
  window = OpenWindowTags(NULL,
    WA_DragBar, TRUE,
    WA_DepthGadget, TRUE,
    WA_PubScreen, screen_lock,
    WA_Width, 417,
    WA_Height, 90,
    WA_CloseGadget, TRUE,
    WA_IDCMP, CLOSEWINDOW|REFRESHWINDOW|BUTTONIDCMP,
    WA_Title, "Command panel",
    WA_Activate, TRUE,
    TAG_DONE);
  if(!window)
    {
    puts("Impossible d'ouvrir la fenetre");
    return(FALSE);
    }

  struct Gadget *gad = CreateContext(&glist);
  struct NewGadget ng;

  /*
  *   On crée la liste pour les touches de fonction
  */

  ng.ng_TextAttr = &Topaz80;
  ng.ng_VisualInfo = vi;
  ng.ng_LeftEdge = 5;
  ng.ng_TopEdge = 12;
  ng.ng_Width = 80;
  ng.ng_Height = 14;
  ng.ng_Flags = 0;
  ng.ng_GadgetText = NULL;

  for(int j=0; j<5; j++)
    {
    for(int i = 0; i<5; i++)
      {
      int k = j*5 + i;
      ng.ng_GadgetID = k;
      if(Panel[k].pa_Set)
        ng.ng_GadgetText = Panel[k].pa_Texte;
      else
        ng.ng_GadgetText = NULL;
      gad = CreateGadget(BUTTON_KIND,gad,&ng,TAG_DONE);
      ng.ng_LeftEdge += 82;
      }
    ng.ng_TopEdge += 15;
    ng.ng_LeftEdge = 5;
    }

  if(!gad)
    {
    puts("Impossible de créer les gadgets");
    return(FALSE);
    }

  AddGList(window,glist,-1,-1,NULL);
  RefreshGList(glist,window,NULL,-1);
  GT_RefreshWindow(window,NULL);
  return(TRUE);
  }




/*
*
*           main()
*
*
*/

int main()

  {
  /*
  *     On vérifie d'abord que nous sommes unique !
  */
  if(FindPort("PANEL_PORT"))
    {
    puts("Mais j'existe déjà !!!");
    exit(10);
    }
  /*
  *     On ouvre la gadget toolkit
  */
  GadToolsBase = OpenLibrary("gadtools.library",36);
  if(!GadToolsBase)
    {
    puts("Impossible d'ouvrir la gadget toolkit");
    exit(10);
    }
  /*
  *     Création du port de Panel
  */
  port = CreatePort("PANEL_PORT",0);
  if(!port)
    {
    puts("Impossible d'ouvrir PANEL_PORT");
    CloseLibrary(GadToolsBase);
    exit(10);
    }
  /*
  *     Maintenant on attend une commande
  *     START en provenance de l'utilisateur
  *     de Term II
  */
  forever
    {
    WaitPort(port);
    struct XCMD *xcmd = GetMsg(port);
    if(xcmd && (xcmd->xcmd_TermCmd == XCMD_START))
      {
      screen_lock = xcmd->xcmd_TermScreen;
      dir_lock    = xcmd->xcmd_TermDir;
      ReplyMsg(xcmd);
      break;
      }
    else
      ReplyMsg(xcmd);
    }
  /*
  *     On se place dans le même répertoire
  *     que Term II pour lire le fichier de
  *     configuration. Mais on sauve le
  *     répertoire courant dans old_lock
  */
  BPTR old_lock = CurrentDir(dir_lock);
  /*
  *     Et on lit le fichier de configuration
  */
  Load();
  /*
  *     Et on affiche le panel
  */
  struct XCMD *xcmd = CreateXCMD(port);
  if(InitPanel() && xcmd)
    {
    BOOL pas_fini = TRUE;
    struct IntuiMessage *msg;
    ULONG IntuiSignal = 1 << window->UserPort->mp_SigBit;
    ULONG XCMDSignal  = 1 << port->mp_SigBit;
    while(pas_fini)
      {
      ULONG signaux = Wait(IntuiSignal|XCMDSignal);
      if(signaux & IntuiSignal)
        {
        /*
        *       Nous avons reçu un signal depuis Intuition
        */
        while(msg = GT_GetIMsg(window->UserPort))
          {
          ULONG class = msg->Class;
          SHORT code = msg->Code;
          struct Gadget *gadget = msg->IAddress;
          GT_ReplyIMsg(msg);
          switch(class)
            {
            case CLOSEWINDOW:
              pas_fini = FALSE;
              break;
            case REFRESHWINDOW:
              GT_BeginRefresh(window);
              GT_EndRefresh(window,TRUE);
              break;
            case GADGETUP:
              /*
              *     Un gadget a été sélectionné :
              *     on envoie la commande associée
              */
              xcmd->xcmd_Command = Panel[gadget->GadgetID].pa_Commande;
              if(SendXCMD(xcmd))
                {
                /*
                *     Il _faut_ attendre la réponse
                *     de Term II
                */
                WaitPort(port);
                GetMsg(port);
                }
              /*
              *     Voilà, c'est fini...
              */
              break;
            }
          }
        }
      if(signaux & XCMDSignal)
        {
        /*
        *       Nous avons reçu une message depuis
        *       Term II. Il ne peut s'agir que d'une
        *       commande QUIT, ou d'un START envoyer
        *       par erreur à l'utilisateur.
        */
        struct XCMD *x = GetMsg(port);
        if(x->xcmd_TermCmd == XCMD_STOP)
          pas_fini = FALSE;
        else
          {
          /*
          *     C'est un STOP envoyé par erreur.
          *     On enlève les lock, et on retourne
          *     le message à Term II
          */
          UnLock(x->xcmd_TermDir);
          UnlockPubScreen(NULL,x->xcmd_TermScreen);
          }
        ReplyMsg(x);
        }
      }
    }
  if(xcmd)
    DeleteXCMD(xcmd);
  if(port)
    DeletePort(port);
  if(window)
    {
    struct IntuiMessage *msg;
    while(msg = GT_GetIMsg(window->UserPort)) GT_ReplyIMsg(msg);
    CloseWindow(window);
    };
  if(vi)
    FreeVisualInfo(vi);
  if(GadToolsBase)
    {
    FreeGadgets(glist);
    UnlockPubScreen(NULL,screen_lock);
    CloseLibrary(GadToolsBase);
    }
  CurrentDir(old_lock);
  UnLock(dir_lock);
  }
