#ifdef THREADSOLARIS

/* SDL include */
#include "scttypes.h"

/* TCP/IP Communication module include */
#include "tcpipcomm.h"

/* Motif includes */
#include <Xm/XmAll.h>
#include <Xm/MainW.h>
#include <Xm/Label.h>

#include <stdio.h>
#include <unistd.h>
#include "string.h"

/* Posix include */
#include "pthread.h"

/* conditional include (depending on which mobileSt block instance is built) */

#ifdef JOHN
#include "john.ifc"
#elif defined MARIE
#include "marie.ifc"
#elif defined PARISPIZZA
#include "parispizza.ifc"
#else
#include "lyonpizza.ifc"
#endif

/* State of GSM Phone */
enum guiState
{
  Off,
  Enter_PIN,
  PIN_Entered,
  WaitCheckPIN,
  Normal,
  Menu_PhoneBook,
  Menu_PhoneBook_John,
  Menu_PhoneBook_Marie,
  Menu_PhoneBook_LyonPizza,
  Menu_PhoneBook_ParisPizza,
  Menu_BillingReport,
  Dialling,
  Ringing,
  Conversation,
  Disabled,
  ReportDuration,
  ReportPrice
};

/* Variable declarations */
enum guiState guistate;
int currentBaseStation;
int duration = 0;
double price = 0;
char billingText[32];
int pinCode = 0;
int hasCalled = 0;
int beingCalled = 0;
XtIntervalId timeInterval;
XtAppContext app;
Display *display;
int guiFD[2]; /* file descriptor for GUI communication */

/* Lists defined in the .cod file */
extern tSDLSignalInfo *xSignalList[];
extern xSignalIdNode xSignalIdList[];

Widget toplevel, 
    main_w, 
    rowcol,
    btnOK,
    btnOnOff,
    btnLeft,
    btnRight,
    btnC,
    btn1,
    btn2,
    btn3,
    btn4,
    btn5,
    btn6,
    btn7,
    btn8,
    btn9,
    btn0,
    lblBst,
    optBst,
    lblTopBmp,
    lblBtmBmp,
    frmDisplay,
    lblDsplText,
    mnuBst,
    mnuItemParis11,
    mnuItemParis12,
    mnuItemLyon11,
    mnuItemLyon12;

/* Declaration of the entry function in the SDL system */
int SDL_Main(int argc, char *argv[]);


/*
  Searches the xSignalList for a tSDLSignalInfo node with name xSignalName.
  The xSignalIdNode with the corresponding index is returned.
  If the data is not found, 0 is returned.
*/
xSignalIdNode xGetSigIdNode(char *xSignalName)
{
  tSDLSignalInfo *xTypeInfoNode;

  int xFound = 0;
  int xIndex = 0;
  int xNotFoundInList = 0;

  while (!xFound)
  {
    xTypeInfoNode = xSignalList[xIndex];

    if (xTypeInfoNode != 0)
    {
      if (strcmp(xSignalName, xTypeInfoNode->Name) == 0)
      {
        xFound = -1;
      }
      else
        xIndex++;
    }
    else
    {
      xFound = -1;
      xNotFoundInList = -1;
    }
  }
  
  if (!xNotFoundInList)
    return xSignalIdList[xIndex];
  else
    return 0; /* A signal with name xSignalName was not found */
}

/* Callback function for the OK button */
void cb_btnOK(Widget w, XtPointer client_data, XtPointer call_data)
{
  xSignalIdNode xSigIdNode;
  xSignalNode xInSignal;
  XmString newText;

  switch(guistate)
  {
    case PIN_Entered:
      /* insert signal PIN */
      guistate = WaitCheckPIN;
      xSigIdNode = xGetSigIdNode("PIN");
      xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv); /* an xSignalNode is returned */

      /* Set param1 to the pin value (PIN_t is an enum, pinCode is an int) */
      ((yPDP_PIN)(xInSignal))->Param1 = pinCode;
      SDL_Output(xInSignal, (xIdNode *)0);	
      break;
    case Normal:
      /* Display "Phone Book >" in display" */
      XLockDisplay(display);
      newText = XmStringCreateLocalized("Phone Book >");
      XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
      XmStringFree(newText);
      guistate = Menu_PhoneBook;
      XUnlockDisplay(display);
      break;
    case Conversation:
      XLockDisplay(display);

      if (!beingCalled)
        hasCalled = -1;
      beingCalled = 0;

      newText = XmStringCreateLocalized("TLOG");
      XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
      XmStringFree(newText);
      guistate = Normal;
      /* Insert on_hook signal */
      xSigIdNode = xGetSigIdNode("on_hook");
      xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);
      SDL_Output(xInSignal, (xIdNode *)0);
      XUnlockDisplay(display);
      break;
    case Ringing:
      /* Insert answer_call signal */
      beingCalled = -1;
      xSigIdNode = xGetSigIdNode("answer_call");
      xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);
      SDL_Output(xInSignal, (xIdNode *)0);
      break;
    case Menu_PhoneBook:
      XLockDisplay(display);
      guistate = Menu_PhoneBook_John;
      /* Display "PhoneBook: John >" */
      newText = XmStringCreateLocalized("John >");
      XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
      XmStringFree(newText);
      XUnlockDisplay(display);
      break;
    case Menu_PhoneBook_John:
      /* Insert dialing(Mobile_ID_t) signal */
      xSigIdNode = xGetSigIdNode("dialing");
      xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);

      /* Set param1 to the destination mobile (Mobile_ID_t is an enum) */
      ((yPDP_dialing)(xInSignal))->Param1 = 2;
      SDL_Output(xInSignal, (xIdNode *)0);
      break;
    case Menu_PhoneBook_Marie:
      /* Insert dialing(Mobile_ID_t) signal */
      xSigIdNode = xGetSigIdNode("dialing");
      xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);

      /* Set param1 to the pin value (Mobile_ID_t is an enum) */
      ((yPDP_dialing)(xInSignal))->Param1 = 1;

      SDL_Output(xInSignal, (xIdNode *)0);
      break;
    case Menu_PhoneBook_LyonPizza:
      /* Insert dialing(Mobile_ID_t) signal */
      xSigIdNode = xGetSigIdNode("dialing");
      xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);

      /* Set param1 to the pin value (Mobile_ID_t is an enum) */
      ((yPDP_dialing)(xInSignal))->Param1 = 5;

      SDL_Output(xInSignal, (xIdNode *)0);
      break;
    case Menu_PhoneBook_ParisPizza:
      /* Insert dialing(Mobile_ID_t) signal */
      xSigIdNode = xGetSigIdNode("dialing");
      xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);

      /* Set param1 to the pin value (Mobile_ID_t is an enum) */
      ((yPDP_dialing)(xInSignal))->Param1 = 4;

      SDL_Output(xInSignal, (xIdNode *)0);
      break;
    case Menu_BillingReport:
      /* Insert askReport signal */
      xSigIdNode = xGetSigIdNode("askReport");
      xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);
      SDL_Output(xInSignal, (xIdNode *)0);
      break;
  }  
}

/* Callback function for the C button */
void cb_btnC(Widget w, XtPointer client_data, XtPointer call_data)
{
  XmString newText;

  switch(guistate)
  {
    case Menu_PhoneBook:
    case Menu_BillingReport:
    case Normal:
      XLockDisplay(display);
      guistate = Normal;
      /* Clear the display */
      newText = XmStringCreateLocalized("TLOG");
      XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
      XmStringFree(newText);
      XUnlockDisplay(display);
      break;
    case ReportDuration:
    case ReportPrice:
      XLockDisplay(display);
      guistate = Menu_BillingReport;
      newText = XmStringCreateLocalized("< Billing Report");
      XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
      XmStringFree(newText);
      XUnlockDisplay(display);
      break;
    case Menu_PhoneBook_John:
    case Menu_PhoneBook_Marie:
    case Menu_PhoneBook_LyonPizza:
    case Menu_PhoneBook_ParisPizza:
      XLockDisplay(display);
      guistate = Menu_PhoneBook;
      /* Display "Phone Book >" */
      newText = XmStringCreateLocalized("PhoneBook >");
      XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
      XmStringFree(newText);
      XUnlockDisplay(display);
      break;
    case PIN_Entered:
      XLockDisplay(display);
      guistate = Enter_PIN;
      /* Update display with "Enter PIN:" */
      newText = XmStringCreateLocalized("Enter PIN:");
      XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
      XmStringFree(newText);
      XUnlockDisplay(display);
      break;
				
      /* state Ringing is not considered for IDC_C, i.e. a call can not be rejected */

    default:
      break;
  }
}

/* Callback function for the OnOff button */
void cb_btnOnOff(Widget w, XtPointer client_data, XtPointer call_data)
{
  xSignalIdNode xSigIdNode;
  xSignalNode xInSignal;
  XmString newText;

  Colormap cmap;
  XColor xcolor, 
         unused;
  Pixel bgColor, 
        fgColor, 
        topShColor, 
        btmShColor, 
        selColor;
  Display *dspl;

  if (guistate == Off)
  {
    XLockDisplay(display);
    guistate = Enter_PIN;

    /* Change display color to "LightBlue" */

    dspl = XtDisplay(frmDisplay);

    XtVaSetValues(frmDisplay, XtVaTypedArg, XmNbackground, XmRString, "LightBlue", strlen("LightBlue")+1, NULL);

    XtVaGetValues(frmDisplay, XmNbackground, &bgColor, XmNcolormap, &cmap, NULL);

    XmGetColors(XtScreen(frmDisplay), cmap, bgColor, &fgColor, &topShColor, &btmShColor, &selColor);

    XtVaSetValues(frmDisplay, XmNtopShadowColor, topShColor, XmNbottomShadowColor, btmShColor, XmNarmColor, selColor, XmNborderColor, fgColor, NULL);

    /* Set the display text */
    newText = XmStringCreateLocalized("Enter PIN:");
    XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
    XmStringFree(newText);
    
    newText = XmStringCreateLocalized("Off");
    XtVaSetValues(btnOnOff, XmNlabelString, newText, NULL);
    XmStringFree(newText);

    /* Insert signal "onKey" */
    xSigIdNode = xGetSigIdNode("onKey");
    xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);
    SDL_Output(xInSignal, (xIdNode *)0);
    XUnlockDisplay(display);
  }
  else
  {
    XLockDisplay(display);
    guistate = Off;

    /* Change display color to "Grey" */

    dspl = XtDisplay(frmDisplay);

    XtVaSetValues(frmDisplay, XtVaTypedArg, XmNbackground, XmRString, "Grey", strlen("Grey")+1, NULL);

    XtVaGetValues(frmDisplay, XmNbackground, &bgColor, XmNcolormap, &cmap, NULL);

    XmGetColors(XtScreen(frmDisplay), cmap, bgColor, &fgColor, &topShColor, &btmShColor, &selColor);

    XtVaSetValues(frmDisplay, XmNtopShadowColor, topShColor, XmNbottomShadowColor, btmShColor, XmNarmColor, selColor, XmNborderColor, fgColor, NULL);
    
    /* Clear the display */
    newText = XmStringCreateLocalized(".");
    XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
    XmStringFree(newText);
    
    newText = XmStringCreateLocalized("On");
    XtVaSetValues(btnOnOff, XmNlabelString, newText, NULL);
    XmStringFree(newText);

    /* Disable base station combobox */
    XtSetSensitive(optBst, False);

    /* Insert signal "offKey" */
    xSigIdNode = xGetSigIdNode("offKey");
    xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);
    SDL_Output(xInSignal, (xIdNode *)0);
    XUnlockDisplay(display);
  }

}

/* Callback function for the '>' button */
void cb_btnRight(Widget w, XtPointer client_data, XtPointer call_data)
{
  XmString newText;

  switch(guistate)
  {
    case Menu_PhoneBook:
      XLockDisplay(display);
      guistate = Menu_BillingReport;
			
      /* Show "< Billing Report" */
      newText = XmStringCreateLocalized("< Billing Report");
      XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
      XmStringFree(newText);
      XUnlockDisplay(display);
      break;
    case Menu_PhoneBook_John:
      XLockDisplay(display);
      guistate = Menu_PhoneBook_Marie;
      /* Show "Phone Book: < Marie >" */
      newText = XmStringCreateLocalized("< Marie >");
      XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
      XmStringFree(newText);
      XUnlockDisplay(display);
      break;
    case Menu_PhoneBook_Marie:
      XLockDisplay(display);
      guistate = Menu_PhoneBook_LyonPizza;
      /* Show "Phone Book: < LyonPizza >" */
      newText = XmStringCreateLocalized("< LyonPizza >");
      XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
      XmStringFree(newText);
      XUnlockDisplay(display);
      break;
    case Menu_PhoneBook_LyonPizza:
      XLockDisplay(display);
      guistate = Menu_PhoneBook_ParisPizza;
      /* Show "Phone Book: < ParisPizza" */
      newText = XmStringCreateLocalized("< ParisPizza >");
      XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
      XmStringFree(newText);
      XUnlockDisplay(display);
      break;
    case ReportDuration:
      XLockDisplay(display);
      guistate = ReportPrice;
      sprintf(billingText, "< Price: %4f", price);
      newText = XmStringCreateLocalized(billingText);
      XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
      XmStringFree(newText);
      XUnlockDisplay(display);
      break;

    default:
      break;
  }
}

/* Callback function for the '<' button */
void cb_btnLeft(Widget w, XtPointer client_data, XtPointer call_data)
{
  XmString newText;

  switch(guistate)
  {
    case Menu_BillingReport:
      XLockDisplay(display);
      guistate = Menu_PhoneBook;
      /* Show "Phone Book >" */
      newText = XmStringCreateLocalized("Phone Book >");
      XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
      XmStringFree(newText);
      XUnlockDisplay(display);
      break;
    case Menu_PhoneBook_Marie:
      XLockDisplay(display);
      guistate = Menu_PhoneBook_John;
      /* Show "Phone Book: John >" */
      newText = XmStringCreateLocalized("John >");
      XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
      XmStringFree(newText);
      XUnlockDisplay(display);
      break;
    case Menu_PhoneBook_LyonPizza:
      XLockDisplay(display);
      guistate = Menu_PhoneBook_Marie;
      /* Show "Phone Book: < Marie >" */
      newText = XmStringCreateLocalized("< Marie >");
      XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
      XmStringFree(newText);
      XUnlockDisplay(display);
      break;
    case Menu_PhoneBook_ParisPizza:
      XLockDisplay(display);
      guistate = Menu_PhoneBook_LyonPizza;
      /* Show "Phone Book: < LyonPizza >" */
      newText = XmStringCreateLocalized("< Lyon Pizza >");
      XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
      XmStringFree(newText);
      XUnlockDisplay(display);
      break;
    case ReportPrice:
      XLockDisplay(display);
      guistate = ReportDuration;
      sprintf(billingText, "Duration: %d >", duration);
      newText = XmStringCreateLocalized(billingText);
      XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
      XmStringFree(newText);
      XUnlockDisplay(display);
      break;
    default:
      break;
  }
}

/* Callback function for the Digit buttons */
void cb_btnDigit(Widget w, XtPointer client_data, XtPointer call_data)
{
  XmString newText;

  if (guistate == Enter_PIN)
  {
    XLockDisplay(display);
    guistate = PIN_Entered;

    if (w == btn0) pinCode = 0;
    else if (w == btn1) pinCode = 1;
    else if (w == btn2) pinCode = 2;
    else if (w == btn3) pinCode = 3;
    else if (w == btn4) pinCode = 4;
    else if (w == btn5) pinCode = 5;
    else if (w == btn6) pinCode = 6;
    else if (w == btn7) pinCode = 7;
    else if (w == btn8) pinCode = 8;
    else if (w == btn9) pinCode = 9;

    /* Update display with "Enter PIN: *" */
    newText = XmStringCreateLocalized("Enter PIN: *");
    XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
    XmStringFree(newText);
    XUnlockDisplay(display);
  }
}

/* Callback function for the buttons in the option menu */
void cb_optBst(Widget w, XtPointer client_data, XtPointer call_data)
{
  xSignalIdNode xSigIdNode;
  xSignalNode xInSignal;

  XLockDisplay(display);

  /* Get the new selection */
  if (w == mnuItemParis11) currentBaseStation = 0;
  else if (w == mnuItemParis12) currentBaseStation = 1;
  else if (w == mnuItemLyon11) currentBaseStation = 2;
  else currentBaseStation = 3;
          
  /* Insert "BTSChanging" into the system */
  xSigIdNode = xGetSigIdNode("BTSchanging");
  xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);
          
  /* Set Param1 to new BTS */
  ((yPDP_BTSchanging)(xInSignal))->Param1 = currentBaseStation;

  SDL_Output(xInSignal, (xIdNode *)0);
  XUnlockDisplay(display);
}

/* Callback function for GUI signals */
void cb_guiSignal(XtPointer client_data, int *fd, XtInputId *id)
{
  unsigned int reportIndice;
  XmString newText;
  WidgetList optMenuButtons;
  int nbrOfButtons;
  int res;
  char buf[32];
  char signalName[32];

  /* read from the descriptor */
  res = read(*fd, buf, 32);
  if (res == -1)
  {
    printf("read: error\n");
    return;
  }

  if (res > 0)
  {
    buf[res] = '\0';
    strncpy(signalName, buf, strlen(buf) - 1);
    printf("signal to GUI: %s\n", signalName);
  }

  /*
    Separate the signals in the displ signallist, as they should be handled by the GUI
    Other signals go via the TCP/IP module
  */
  if (!strcmp(signalName, "badPIN"))
  {
    /* Show "Bad PIN" message in text box. */
    XLockDisplay(display);
    newText = XmStringCreateLocalized("Enter PIN:"); /* Bad PIN */
    XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
    XmStringFree(newText);

    guistate = Enter_PIN;
    XUnlockDisplay(display);
  }
  else if (!strcmp(signalName, "disable"))
  {
    /* Disable phone. Set text "Disabled". The phone is still on */
    XLockDisplay(display);
    guistate = Disabled;
    newText = XmStringCreateLocalized("Disabled");
    XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
    XmStringFree(newText);
    XtSetSensitive(optBst, False);
    XUnlockDisplay(display);
  }
  else if (!strcmp(signalName, "initGUI"))
  {
    XLockDisplay(display);
    XtSetSensitive(btnOnOff, True);
    XmStringFree(newText);

    /* set default basestation to Paris11 */
    XtVaGetValues( mnuBst, XmNnumChildren, &nbrOfButtons,
        XmNchildren, &optMenuButtons, NULL);
    XtVaSetValues(optBst, XmNmenuHistory, 
        optMenuButtons[0], NULL);
    XUnlockDisplay(display);
  }
  else if (!strcmp(signalName, "rejected"))
  {
    /* Set text to "Call rejected" */
    XLockDisplay(display);
    newText = XmStringCreateLocalized("Call rejected");
    XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
    XmStringFree(newText);
    guistate = Normal;
    XUnlockDisplay(display);
  }
  else if (!strcmp(signalName, "ring"))
  {
    XLockDisplay(display);
    guistate = Ringing;
    /* Set the display text to "Incoming call" */
    newText = XmStringCreateLocalized("Incoming call");
    XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
    XmStringFree(newText);
    XUnlockDisplay(display);
  }
  else if (!strcmp(signalName, "unlock"))
  {
    /* Set text to PIN OK */
    XLockDisplay(display);
    newText = XmStringCreateLocalized("PIN OK");
    XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
    XmStringFree(newText);
    /* Enable base station combobox */
    XtSetSensitive(optBst, True);
    guistate = Normal;
    XUnlockDisplay(display);
  }
  else if (!strcmp(signalName, "convers"))
  {
    /* Set text to "Conversation" */
    XLockDisplay(display);

    guistate = Conversation;
    newText = XmStringCreateLocalized("Conversation");
    XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
    XmStringFree(newText);
    XUnlockDisplay(display);
  }
  else if (!strcmp(signalName, "busy"))
  {
    /* set display text to "Busy" */
    XLockDisplay(display);
    newText = XmStringCreateLocalized("Busy");
    XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
    XmStringFree(newText);
    guistate = Normal;
    XUnlockDisplay(display);
  }
  else if (!strcmp(signalName, "unreachable"))
  {
    /* set display text to "Unreachable" */
    XLockDisplay(display);
    newText = XmStringCreateLocalized("Unreachable");
    XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
    XmStringFree(newText);
    guistate = Normal;
    XUnlockDisplay(display);
  }
  else if (!strcmp(signalName, "giveReport"))
  {
    /* Report information to display about the latest call */
    XLockDisplay(display);
    guistate = ReportDuration;

    sprintf(billingText, "Duration: %d >", duration);
    newText = XmStringCreateLocalized(billingText);
    XtVaSetValues(lblDsplText, XmNlabelString, newText, NULL);
    XmStringFree(newText);
    XUnlockDisplay(display);
  }
  else
    printf("Unknown signal: %s\n", signalName);

  return;
}

int main(int argc, char *argv[])
{
  Arg args[2];

  Pixmap phoneTop, phoneBottom;

  Colormap cmap;
  XColor xcolor, 
         unused;
  Pixel bgColor, 
        fgColor, 
        topShColor, 
        btmShColor, 
        selColor;
  Display *dspl;

  XmString bstParis11, 
           bstParis12, 
           bstLyon11, 
           bstLyon12, 
           bstLabel;

  Screen *scrn;
  Dimension width, height;
  Position x, y;

  pthread_t sdlThr;
  pthread_attr_t sdlThrAttr;

  if (XInitThreads() == 0)
  {
    printf("XInitThreads: initialization error\n");
    exit(1);
  }

  if (pipe(guiFD) != 0)
  {
    printf("pipe: creation error\n");
    exit(1);
  }

  XtSetLanguageProc(NULL, NULL, NULL);
  
  toplevel = XtAppInitialize(
               &app, 
               "gsmgui", 
               NULL, 
               0, 
               &argc, 
               argv, 
               NULL, 
               NULL, 
               NULL);

  main_w = XtVaCreateManagedWidget(
	       "form",
	       xmFormWidgetClass,
	       toplevel,
               NULL);

  phoneTop = XmGetPixmap(
               XtScreen(toplevel), 
               "PHTP.xbm",
               BlackPixelOfScreen(XtScreen(toplevel)),
               WhitePixelOfScreen(XtScreen(toplevel)));

  phoneBottom = XmGetPixmap(
               XtScreen(toplevel), 
               "PHBT.xbm",
               BlackPixelOfScreen(XtScreen(toplevel)),
               WhitePixelOfScreen(XtScreen(toplevel)));

 
  /* Create top bitmap: XmLabel */
  lblTopBmp = XtVaCreateManagedWidget(
            "TOP",
            xmLabelWidgetClass,
            main_w,
            XmNlabelType,
            XmPIXMAP,
            XmNlabelPixmap,
            phoneTop,
            NULL);

  /* Create DisplayFrame: Frame */
  frmDisplay = XtVaCreateManagedWidget(
	     "", 
             xmFrameWidgetClass, 
             main_w, 
             XmNshadowType, 
             XmSHADOW_IN, 
             NULL);

  /* Set the global Display variable */
  display = XtDisplay(main_w);

  /* Create text in frame: XmLabel */
  lblDsplText = XtVaCreateManagedWidget(
	     ".", 
             xmLabelGadgetClass, 
             frmDisplay,
             NULL);

  /* Create a form widget with a fraction base of 3 
     for arranging buttons */
  rowcol = XtVaCreateManagedWidget(
             "rowcol",
	     xmFormWidgetClass, 
             main_w, 
             XmNfractionBase, 3, 
             NULL);
  
  /* Create btnOK : XmPushButton */
  btnOK= XtVaCreateManagedWidget(
            "OK", 
            xmPushButtonWidgetClass, 
            rowcol,
	    XtVaTypedArg, 
            XmNlabelString, 
            XmRString,
	    "OK",
            (strlen("OK")+1),
            XmNtopAttachment, XmATTACH_FORM,
	    XmNleftAttachment, XmATTACH_POSITION,
	    XmNleftPosition, 0,
	    XmNrightAttachment, XmATTACH_POSITION,
            XmNrightPosition, 1,
            0);

  /* Add callback function to btnOK */
  XtAddCallback(btnOK, XmNactivateCallback, cb_btnOK, NULL);

  /* Create: btnRIGHT : XmPushButton */
  btnRight = XtVaCreateManagedWidget(
            "RIGHT", 
            xmPushButtonWidgetClass, 
            rowcol,
            XtVaTypedArg, 
            XmNlabelString, 
            XmRString,
	    ">",
            (strlen(">")+1),
            XmNtopAttachment, XmATTACH_FORM,
	    XmNleftAttachment, XmATTACH_POSITION,
	    XmNleftPosition, 1,
	    XmNrightAttachment, XmATTACH_POSITION,
            XmNrightPosition, 2,
            0);

  /* Add callback function to btnRight */
  XtAddCallback(btnRight, XmNactivateCallback, cb_btnRight, NULL);

  /* Create btnC : XmPushButton */
  btnC = XtVaCreateManagedWidget(
            "C",
            xmPushButtonWidgetClass,
            rowcol,
            XtVaTypedArg, 
            XmNlabelString,
            XmRString,
	    "C",
            (strlen("C")+1),
            XmNtopAttachment, XmATTACH_FORM,
	    XmNleftAttachment, XmATTACH_POSITION,
	    XmNleftPosition, 2,
	    XmNrightAttachment, XmATTACH_POSITION,
            XmNrightPosition, 3,
            0);
   
  /* Add callback function to btnC */
  XtAddCallback(btnC, XmNactivateCallback, cb_btnC, NULL);

  /* Create btnOnOff : XmPushButton */
  btnOnOff = XtVaCreateManagedWidget(
            "ON",
            xmPushButtonWidgetClass, 
            rowcol,
	    XtVaTypedArg, 
            XmNlabelString, 
            XmRString,
	    "ON",
            (strlen("ON")+1),
            XmNtopAttachment, XmATTACH_WIDGET,
            XmNtopWidget, btnOK,
	    XmNleftAttachment, XmATTACH_POSITION,
	    XmNleftPosition, 0,
	    XmNrightAttachment, XmATTACH_POSITION,
            XmNrightPosition, 1,
            0);

  /* Add callback function to btnOnOff */
  XtAddCallback(btnOnOff, XmNactivateCallback, cb_btnOnOff, NULL);

  /* Create btnLeft : XmPushButton */
  btnLeft= XtVaCreateManagedWidget(
            "LEFT", 
            xmPushButtonWidgetClass, 
            rowcol,
            XtVaTypedArg, 
            XmNlabelString, 
            XmRString,
	    "<",
            (strlen("<")+1),
            XmNtopAttachment, XmATTACH_WIDGET,
            XmNtopWidget, btnRight,
	    XmNleftAttachment, XmATTACH_POSITION,
	    XmNleftPosition, 1,
	    XmNrightAttachment, XmATTACH_POSITION,
            XmNrightPosition, 2,
            0);

  /* Add callback function to btnOK */
  XtAddCallback(btnLeft, XmNactivateCallback, cb_btnLeft, NULL);

  /* Create BTN1 : XmPushButton */
  btn1 = XtVaCreateManagedWidget(
            "1", 
            xmPushButtonWidgetClass, 
            rowcol,
	    XtVaTypedArg, 
            XmNlabelString, 
            XmRString,
	    "1",
            (strlen("1")+1),
            XmNtopAttachment, XmATTACH_WIDGET,
            XmNtopWidget, btnOnOff,
	    XmNleftAttachment, XmATTACH_POSITION,
	    XmNleftPosition, 0,
	    XmNrightAttachment, XmATTACH_POSITION,
            XmNrightPosition, 1,
            0);

  /* Add callback function to btn1 */
  XtAddCallback(btn1, XmNactivateCallback, cb_btnDigit, NULL);

  /* Create: BTN2 : XmPushButton */
  btn2 = XtVaCreateManagedWidget(
            "2", 
            xmPushButtonWidgetClass, 
            rowcol,
            XtVaTypedArg, 
            XmNlabelString, 
            XmRString,
	    "2",
            (strlen("2")+1),
            XmNtopAttachment, XmATTACH_WIDGET,
            XmNtopWidget, btnLeft,
	    XmNleftAttachment, XmATTACH_POSITION,
	    XmNleftPosition, 1,
	    XmNrightAttachment, XmATTACH_POSITION,
            XmNrightPosition, 2,
            0);

  /* Add callback function to btn1 */
  XtAddCallback(btn2, XmNactivateCallback, cb_btnDigit, NULL);

  /* Create: BTN3 : XmPushButton */
  btn3 = XtVaCreateManagedWidget(
            "3",
            xmPushButtonWidgetClass,
            rowcol,
            XtVaTypedArg, 
            XmNlabelString,
            XmRString,
	    "3",
            (strlen("3")+1),
            XmNtopAttachment, XmATTACH_WIDGET,
            XmNtopWidget, btnLeft,
	    XmNleftAttachment, XmATTACH_POSITION,
	    XmNleftPosition, 2,
	    XmNrightAttachment, XmATTACH_POSITION,
            XmNrightPosition, 3,
            0);
  
  /* Add callback function to btn3 */
  XtAddCallback(btn3, XmNactivateCallback, cb_btnDigit, NULL);

  /* Create: BTN4 : XmPushButton */
  btn4 = XtVaCreateManagedWidget(
            "4", 
            xmPushButtonWidgetClass, 
            rowcol,
	    XtVaTypedArg, 
            XmNlabelString, 
            XmRString,
	    "4",
            (strlen("4")+1),
            XmNtopAttachment, XmATTACH_WIDGET,
            XmNtopWidget, btn1,
	    XmNleftAttachment, XmATTACH_POSITION,
	    XmNleftPosition, 0,
	    XmNrightAttachment, XmATTACH_POSITION,
            XmNrightPosition, 1,
            0);

  /* Add callback function to btn4 */
  XtAddCallback(btn4, XmNactivateCallback, cb_btnDigit, NULL);

  /* Create: BTN5 : XmPushButton */
  btn5 = XtVaCreateManagedWidget(
            "5", 
            xmPushButtonWidgetClass, 
            rowcol,
            XtVaTypedArg, 
            XmNlabelString, 
            XmRString,
	    "5",
            (strlen("5")+1),
            XmNtopAttachment, XmATTACH_WIDGET,
            XmNtopWidget, btn2,
	    XmNleftAttachment, XmATTACH_POSITION,
	    XmNleftPosition, 1,
	    XmNrightAttachment, XmATTACH_POSITION,
            XmNrightPosition, 2,
            0);

  /* Add callback function to btn5 */
  XtAddCallback(btn5, XmNactivateCallback, cb_btnDigit, NULL);

  /* Create: BTN6 : XmPushButton */
  btn6 = XtVaCreateManagedWidget(
            "6",
            xmPushButtonWidgetClass,
            rowcol,
            XtVaTypedArg, 
            XmNlabelString,
            XmRString,
	    "6",
            (strlen("6")+1),
            XmNtopAttachment, XmATTACH_WIDGET,
            XmNtopWidget, btn3,
	    XmNleftAttachment, XmATTACH_POSITION,
	    XmNleftPosition, 2,
	    XmNrightAttachment, XmATTACH_POSITION,
            XmNrightPosition, 3,
            0);
  
  /* Add callback function to btn6 */
  XtAddCallback(btn6, XmNactivateCallback, cb_btnDigit, NULL);
 
  /* Create: BTN7 : XmPushButton */
  btn7 = XtVaCreateManagedWidget(
            "7", 
            xmPushButtonWidgetClass, 
            rowcol,
	    XtVaTypedArg, 
            XmNlabelString, 
            XmRString,
	    "7",
            (strlen("7")+1),
            XmNtopAttachment, XmATTACH_WIDGET,
            XmNtopWidget, btn4,
	    XmNleftAttachment, XmATTACH_POSITION,
	    XmNleftPosition, 0,
	    XmNrightAttachment, XmATTACH_POSITION,
            XmNrightPosition, 1,
            0);

  /* Add callback function to btn7 */
  XtAddCallback(btn7, XmNactivateCallback, cb_btnDigit, NULL);

  /* Create: BTN8 : XmPushButton */
  btn8 = XtVaCreateManagedWidget(
            "8", 
            xmPushButtonWidgetClass, 
            rowcol,
            XtVaTypedArg, 
            XmNlabelString, 
            XmRString,
	    "8",
            (strlen("8")+1),
            XmNtopAttachment, XmATTACH_WIDGET,
            XmNtopWidget, btn5,
	    XmNleftAttachment, XmATTACH_POSITION,
	    XmNleftPosition, 1,
	    XmNrightAttachment, XmATTACH_POSITION,
            XmNrightPosition, 2,
            0);

  /* Add callback function to btn8 */
  XtAddCallback(btn8, XmNactivateCallback, cb_btnDigit, NULL);

  /* Create: BTN9 : XmPushButton */
  btn9 = XtVaCreateManagedWidget(
            "9",
            xmPushButtonWidgetClass,
            rowcol,
            XtVaTypedArg, 
            XmNlabelString,
            XmRString,
	    "9",
            (strlen("9")+1),
            XmNtopAttachment, XmATTACH_WIDGET,
            XmNtopWidget, btn6,
	    XmNleftAttachment, XmATTACH_POSITION,
	    XmNleftPosition, 2,
	    XmNrightAttachment, XmATTACH_POSITION,
            XmNrightPosition, 3,
            0);
  
  /* Add callback function to btn9 */
  XtAddCallback(btn9, XmNactivateCallback, cb_btnDigit, NULL);
 
  /* Create: BTN0 : XmPushButton */
  btn0 = XtVaCreateManagedWidget(
            "0", 
            xmPushButtonWidgetClass, 
            rowcol,
            XtVaTypedArg, 
            XmNlabelString, 
            XmRString,
	    "0",
            (strlen("0")+1),
            XmNtopAttachment, XmATTACH_WIDGET,
            XmNtopWidget, btn8,
	    XmNleftAttachment, XmATTACH_POSITION,
	    XmNleftPosition, 1,
	    XmNrightAttachment, XmATTACH_POSITION,
            XmNrightPosition, 2,
            0);

  /* Add callback function to btn0 */
  XtAddCallback(btn0, XmNactivateCallback, cb_btnDigit, NULL);

  /* Create: BOTTOM : XmLabel */
  lblBtmBmp = XtVaCreateManagedWidget(
            "BOTTOM",
            xmLabelWidgetClass,
            main_w,
            XmNlabelType,
            XmPIXMAP,
            XmNlabelPixmap,
            phoneBottom,
            NULL);

  /* Create Base Station label */
  lblBst = XtVaCreateManagedWidget(
            "BaseStation", 
            xmLabelWidgetClass, 
            main_w,
   	    XtVaTypedArg, 
            XmNlabelString, 
            XmRString,
	    "Base Station", 
            (strlen("Base Station")+1),
            0);


  /* Create base station option menu */
  mnuBst = XmCreatePulldownMenu(
	    main_w,
	    "optPulldown",
	    NULL,
            0);

  XtSetArg(args[0], XmNsubMenuId, mnuBst);
  XtSetArg(args[1], XmNlabelString, bstLabel);


  optBst = XmCreateOptionMenu(
	    main_w,
	    "BstOptionMenu",
            args,
	    1);

  mnuItemParis11 = XtVaCreateManagedWidget(
	    "Paris11", 
	    xmPushButtonGadgetClass, 
            mnuBst, 
            NULL);

  mnuItemParis12 = XtVaCreateManagedWidget(
	    "Paris12", 
	    xmPushButtonGadgetClass, 
            mnuBst, 
            NULL);

  mnuItemLyon11 = XtVaCreateManagedWidget(
	    "Lyon11", 
	    xmPushButtonGadgetClass, 
            mnuBst, 
            NULL);

  mnuItemLyon12 = XtVaCreateManagedWidget(
	    "Lyon12", 
	    xmPushButtonGadgetClass, 
            mnuBst, 
            NULL);

  /* Add callback function to optBst buttons */
  XtAddCallback(mnuItemParis11, XmNactivateCallback, cb_optBst, NULL);  
  XtAddCallback(mnuItemParis12, XmNactivateCallback, cb_optBst, NULL);
  XtAddCallback(mnuItemLyon11, XmNactivateCallback, cb_optBst, NULL);
  XtAddCallback(mnuItemLyon12, XmNactivateCallback, cb_optBst, NULL);


  XtManageChild(optBst);


  /* Alignment: TOP : XmLabel */
  XtVaSetValues(lblTopBmp,

    XmNtopAttachment, XmATTACH_FORM,
    XmNtopOffset,     0,
    XmNtopPosition,   0,
    XmNtopWidget,     0,

    XmNbottomAttachment, XmATTACH_NONE,
    XmNbottomOffset,     0,
    XmNbottomPosition,   0,
    XmNbottomWidget,     0,

    XmNleftAttachment, XmATTACH_FORM,
    XmNleftOffset,     0,
    XmNleftPosition,   0,
    XmNleftWidget,     0,

    XmNrightAttachment, XmATTACH_NONE,
    XmNrightOffset,     0,
    XmNrightPosition,   0,
    XmNrightWidget,     0,
                0 );

  /* Alignment frmDISPLAY */
  XtVaSetValues(frmDisplay,

    XmNtopAttachment, XmATTACH_WIDGET,
    XmNtopOffset,     0,
    XmNtopPosition,   0,
    XmNtopWidget,     lblTopBmp,

    XmNbottomAttachment, XmATTACH_NONE,
    XmNbottomOffset,     0,
    XmNbottomPosition,   0,
    XmNbottomWidget,     0,

    XmNleftAttachment, XmATTACH_FORM,
    XmNleftOffset,     10,
    XmNleftPosition,   0,
    XmNleftWidget,     0,

    XmNrightAttachment, XmATTACH_FORM,
    XmNrightOffset,     10,
    XmNrightPosition,   0,
    XmNrightWidget,     0,
                0 );

  /* Set color for frmDisplay */
  dspl = XtDisplay(frmDisplay);

  XtVaSetValues(frmDisplay, XtVaTypedArg, XmNbackground, XmRString, "Grey", strlen("Grey")+1, NULL);

  XtVaGetValues(frmDisplay, XmNbackground, &bgColor, XmNcolormap, &cmap, NULL);

  XmGetColors(XtScreen(frmDisplay), cmap, bgColor, &fgColor, &topShColor, &btmShColor, &selColor);

  XtVaSetValues(frmDisplay, XmNtopShadowColor, topShColor, XmNbottomShadowColor, btmShColor, XmNarmColor, selColor, XmNborderColor, fgColor, NULL);

  /* Set color for other widgets */
  XmChangeColor(main_w, bgColor);
  XmChangeColor(rowcol, bgColor);
  XmChangeColor(btnOK, bgColor);
  XmChangeColor(btnOnOff, bgColor);
  XmChangeColor(btnLeft, bgColor);
  XmChangeColor(btnRight, bgColor);
  XmChangeColor(btnC, bgColor);
  XmChangeColor(btn1, bgColor);
  XmChangeColor(btn2, bgColor);
  XmChangeColor(btn3, bgColor);
  XmChangeColor(btn4, bgColor);
  XmChangeColor(btn5, bgColor);
  XmChangeColor(btn6, bgColor);
  XmChangeColor(btn7, bgColor);
  XmChangeColor(btn8, bgColor);
  XmChangeColor(btn9, bgColor);
  XmChangeColor(btn0, bgColor);
  XmChangeColor(lblBst, bgColor);
  XmChangeColor(optBst, bgColor);
  XmChangeColor(lblTopBmp, bgColor);
  XmChangeColor(lblBtmBmp, bgColor);
  XmChangeColor(mnuBst, bgColor);

  /* Alignment rowcol */
  XtVaSetValues( rowcol,

    XmNtopAttachment, XmATTACH_WIDGET,
    XmNtopOffset,     5,
    XmNtopPosition,   0,
    XmNtopWidget,     frmDisplay,

    XmNbottomAttachment, XmATTACH_NONE,
    XmNbottomOffset,     0,
    XmNbottomPosition,   0,
    XmNbottomWidget,     0,

    XmNleftAttachment, XmATTACH_FORM,
    XmNleftOffset,     10,
    XmNleftPosition,   0,
    XmNleftWidget,     0,

    XmNrightAttachment, XmATTACH_FORM,
    XmNrightOffset,     10,
    XmNrightPosition,   0,
    XmNrightWidget,     0,
                0 );

  /* Alignment: lblBtmBmp : XmLabel */
  XtVaSetValues(lblBtmBmp,

    XmNtopAttachment, XmATTACH_WIDGET,
    XmNtopOffset,     0,
    XmNtopPosition,   0,
    XmNtopWidget,     rowcol,

    XmNbottomAttachment, XmATTACH_NONE,
    XmNbottomOffset,     0,
    XmNbottomPosition,   0,
    XmNbottomWidget,     0,

    XmNleftAttachment, XmATTACH_FORM,
    XmNleftOffset,     0,
    XmNleftPosition,   0,
    XmNleftWidget,     0,

    XmNrightAttachment, XmATTACH_NONE,
    XmNrightOffset,     0,
    XmNrightPosition,   0,
    XmNrightWidget,     0,
                0 );

  /* Alignment: lblBst : XmLabel */
  XtVaSetValues(lblBst,

    XmNtopAttachment, XmATTACH_WIDGET,
    XmNtopOffset,     0,
    XmNtopPosition,   0,
    XmNtopWidget,     lblBtmBmp,

    XmNbottomAttachment, XmATTACH_NONE,
    XmNbottomOffset,     0,
    XmNbottomPosition,   0,
    XmNbottomWidget,     0,

    XmNleftAttachment, XmATTACH_FORM,
    XmNleftOffset,     10,
    XmNleftPosition,   0,
    XmNleftWidget,     0,

    XmNrightAttachment, XmATTACH_NONE,
    XmNrightOffset,     0,
    XmNrightPosition,   0,
    XmNrightWidget,     0,
                0 );

  /* Alignment: bstOptionMenu */
  XtVaSetValues(optBst,

    XmNtopAttachment, XmATTACH_WIDGET,
    XmNtopOffset,     0,
    XmNtopPosition,   0,
    XmNtopWidget,     lblBst,

    XmNbottomAttachment, XmATTACH_FORM,
    XmNbottomOffset,     0,
    XmNbottomPosition,   0,
    XmNbottomWidget,     0,

    XmNleftAttachment, XmATTACH_FORM,
    XmNleftOffset,     0,
    XmNleftPosition,   0,
    XmNleftWidget,     0,

    XmNrightAttachment, XmATTACH_FORM,
    XmNrightOffset,     0,
    XmNrightPosition,   0,
    XmNrightWidget,     0,
                0 );

  /* ----------------------------------------- */

  XtRealizeWidget(toplevel);

  /* Position the window */
  scrn = XtScreen(toplevel);
  XtVaGetValues(main_w, XmNwidth, &width,
		XmNheight, &height, NULL);

#ifdef MARIE
  x = 0;
  y = 0;
#elif defined JOHN
  x = 0;
  y = HeightOfScreen(scrn) - height;
#elif defined PARISPIZZA
  x = WidthOfScreen(scrn) - width;
  y = 0;
#elif defined LYONPIZZA
  x = WidthOfScreen(scrn) - width;
  y = HeightOfScreen(scrn) - height;
#endif
  XtVaSetValues(main_w, XmNx, x, XmNy, y, NULL);

  /* Set state of GUI to "Off" */
  guistate = Off;

  /* Make the OnOff button and option menu insensitive to input */
  XtSetSensitive(btnOnOff, False);
  XtSetSensitive(optBst, False);

  /* Add a callback function for the guiFD (called when data is avaliable on guiFD[1]) */
  XtAppAddInput(app, guiFD[1], XtInputReadMask, cb_guiSignal, NULL);

  /* Create SDL system thread */
  pthread_attr_init(&sdlThrAttr);
  pthread_attr_setdetachstate(&sdlThrAttr, PTHREAD_CREATE_DETACHED);
  pthread_create(&sdlThr, &sdlThrAttr, SDL_Main, (void*)0);

  XtAppMainLoop(app);
}

/*
  Method for separating signals to the GUI from signals to the TCP/IP module
  GUI signals are processed
  TCP/IP module signals are passed on to the TCP/IP module
*/
void xSendSignalToGUI(xSignalNode *xOutSignal, char *xSignalName)
{
  unsigned int reportIndice;
  char signalName[32];
  int res;
  /*
    Separate the signals in the displ signallist, as they should be handled by the GUI
    Other signals go via the TCP/IP module
  */
  if ((!strcmp(xSignalName, "badPIN"))     ||
      (!strcmp(xSignalName, "disable"))    ||
      (!strcmp(xSignalName, "initGUI"))    ||
      (!strcmp(xSignalName, "rejected"))   ||
      (!strcmp(xSignalName, "ring"))       ||
      (!strcmp(xSignalName, "unlock"))     ||
      (!strcmp(xSignalName, "convers"))    ||
      (!strcmp(xSignalName, "busy"))       ||
      (!strcmp(xSignalName, "unreachable"))||
      (!strcmp(xSignalName, "giveReport")))
  {
    if (!strcmp(xSignalName, "giveReport"))
    {
      reportIndice = ((yPDP_giveReport)(*xOutSignal))->Param1.nb_com - 1; /* latest call = number of calls - 1 */
      duration =    (((yPDP_giveReport)(*xOutSignal))->Param1).bil.A[reportIndice].duration;
      price =       (((yPDP_giveReport)(*xOutSignal))->Param1).bil.A[reportIndice].price;

      if (!hasCalled)
        duration = 0;
    }

    /* Write data on the GUI file descriptor. Use '%' as a terminator */
    strcpy(signalName, xSignalName);
    strcat(signalName, "%\0");
    res = write(guiFD[0], signalName, strlen(signalName));

    if (res < strlen(signalName))
    {
      printf("write: all data not written\n");
    }

  }
  else
    /* Send the signal via the TCP/IP interface */
    xSendSignal(xOutSignal, xSignalName);

  return;
}

#elif defined THREADWIN32

/* Platform includes */
#include <windows.h>
#include "resource.h"
#include "stdio.h"

/* SDL include */
#include "scttypes.h"

/* TCP/IP Communication module include */
#include "tcpipcomm.h"

/* conditional include (depending on which mobileSt block instance is built) */
#ifdef JOHN
#include "john.ifc"
#elif defined MARIE
#include "marie.ifc"
#elif defined PARISPIZZA
#include "parispizza.ifc"
#else
#include "lyonpizza.ifc"
#endif

enum guiState
{
  Off,
  Enter_PIN,
  PIN_Entered,
  WaitCheckPIN,
  Normal,
  Menu_PhoneBook,
  Menu_PhoneBook_John,
  Menu_PhoneBook_Marie,
  Menu_PhoneBook_LyonPizza,
  Menu_PhoneBook_ParisPizza,
  Menu_BillingReport,
  Dialling,
  Ringing,
  Conversation,
  Disabled,
  ReportDuration,
  ReportPrice
};


/* Function declarations */

int SDL_Main(int argc, char *argv[]);

BOOL CALLBACK DialogProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);


/* Variable declarations */

enum guiState guistate;
int currentBaseStation;
HBRUSH displayBrush;
HINSTANCE TheInstance = 0;
HWND hDialog = 0;
int duration = 0;
double price = 0;
int beingCalled = 0;
int hasCalled = 0;
char billingText[32];
int pinCode = 0;

/* Lists defined in the .cod file */
extern tSDLSignalInfo *xSignalList[];
extern xSignalIdNode xSignalIdList[];


/*
  Searches the xSignalList for a tSDLSignalInfo node with name xSignalName.
  The xSignalIdNode with the corresponding index is returned.
  If the data is not found, 0 is returned.
*/
xSignalIdNode xGetSigIdNode(char *xSignalName)
{
  tSDLSignalInfo *xTypeInfoNode;

  int xFound = 0;
  int xIndex = 0;
  int xNotFoundInList = 0;

  while (!xFound)
  {
    xTypeInfoNode = xSignalList[xIndex];

    if (xTypeInfoNode != 0)
    {
      if (strcmp(xSignalName, xTypeInfoNode->Name) == 0)
      {
        xFound = -1;
      }
      else
        xIndex++;
    }
    else
    {
      xFound = -1;
      xNotFoundInList = -1;
    }
  }
  
  if (!xNotFoundInList)
    return xSignalIdList[xIndex];
  else
    return 0; /* A signal with name xSignalName was not found */
}


/*
  Application entry point
  Starts a thread which handles the GUI input
  Starts the SDL system by calling SDL_Main 
    (the "main" function of the SDL system has been renamed "SDL_Main" using XMAIN_NAME)
*/
int WINAPI WinMain
   (HINSTANCE hInst, HINSTANCE hPrevInst, char * cmdParam, int cmdShow)
{
  char *slashPos;
	char exeName[64];
  DWORD xThrId;
  LPSTR cmdLine;
  MSG  msg;
  int status;
  RECT wRect, desktopRect;
  LONG x,y,w,h;
  
	TheInstance = hInst;

  hDialog = CreateDialog (hInst, MAKEINTRESOURCE (DLG_MAIN), 0, DialogProc);

  if (!hDialog)
  {
    char buf [100];
    wsprintf (buf, "Error x%x", GetLastError ());
    MessageBox (0, buf, "CreateDialog", MB_ICONEXCLAMATION | MB_OK);
    return 1;
  }

  memset(billingText, 0, sizeof(billingText));

  // Set the window name to the name of the executable
  cmdLine = GetCommandLine();

  // Look for the last '\' and throw away everything left of it
  slashPos = strrchr(cmdLine, '\\');
  memset(exeName, 0, sizeof(exeName));

  if (slashPos != 0)
    strncpy(exeName, slashPos + 1, strlen(slashPos) - 6);
  else
    strcpy(exeName, cmdLine);

  if (exeName[strlen(exeName) - 1] == '.')
    exeName[strlen(exeName) - 1] = '\0';
  
  SetWindowText(hDialog, exeName);

  GetWindowRect(hDialog, &wRect);
  SystemParametersInfo(SPI_GETWORKAREA, 0, &desktopRect, 0);

  w = wRect.right - wRect.left;
  h = wRect.bottom - wRect.top;


  #ifdef JOHN
  /* lower left corner */
  x = 0;
  y = desktopRect.bottom - h;
  #elif defined MARIE
  /* upper left corner */
  x = 0;
  y = 0;
  #elif defined PARISPIZZA
  /* upper right corner */
  x = desktopRect.right - w;
  y = 0;
  #else
  /* lower right corner */
  x = desktopRect.right - w;
  y = desktopRect.bottom - h;
  #endif

  SetWindowPos(hDialog, HWND_TOP, x, y, w, h, 0);

  /* Create a thread for SDL_Main */
  if (CreateThread(0,0, (LPTHREAD_START_ROUTINE)SDL_Main, (LPVOID)0, 0, (LPDWORD)&xThrId) == NULL)
    return GetLastError();
   
  while ((status = GetMessage (& msg, 0, 0, 0)) != 0)
  {
    if (status == -1)
      return -1;

    if (!IsDialogMessage (hDialog, & msg))
    {
      TranslateMessage ( & msg );
      DispatchMessage ( & msg );
    }
  }

  return msg.wParam;
}


/*
  Message handling callback function
*/
BOOL CALLBACK DialogProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  xSignalIdNode xSigIdNode;
  xSignalNode xInSignal;
  HDC hDc;
  char buffer[64];
  HWND dlgItem = 0;

  switch (message)
  {
    case WM_INITDIALOG:

      /* Insert base station entries into the combo box
         The combobox is set not to sort the items,
         which gives them the same order as the enum BTS_ID_t */
	    dlgItem = GetDlgItem(hwnd, IDC_BASESTNCOMBO);
	    SendMessage(dlgItem, CB_ADDSTRING, 0, (LPARAM)&"Paris11");
	    SendMessage(dlgItem, CB_ADDSTRING, 0, (LPARAM)&"Paris12");
      SendMessage(dlgItem, CB_ADDSTRING, 0, (LPARAM)&"Lyon11");
	    SendMessage(dlgItem, CB_ADDSTRING, 0, (LPARAM)&"Lyon12");

	    currentBaseStation = 0; /* Default base station is Paris11 */
	    SendMessage(dlgItem, CB_SETCURSEL, currentBaseStation, 0);
      EnableWindow(dlgItem, FALSE);
      EnableWindow(GetDlgItem(hwnd, IDC_ONOFF), FALSE);
      
	  return TRUE;

    case WM_CTLCOLORSTATIC:
      /* The static text box should have its background color set if the phone is "On" */
      if ( GetDlgItem(hwnd, IDC_DISPLAY) == (HWND)lParam)
      {
        if (guistate != Off)
        {
          COLORREF c = RGB(100,210,210);

          SetBkColor((HDC)wParam, c);

          /* Return the control background brush (for redraw when window is "damaged") */
          displayBrush = CreateSolidBrush(c);
          return (BOOL)displayBrush;
        }
        else
        /* Phone is off */
          return FALSE;
      }
      else
        /* Other static control than the display */
        return FALSE;

    case WM_COMMAND:
      /* Check the control identifier */
	    switch (LOWORD(wParam))
      {
        case IDC_OK:
          if (HIWORD(wParam) == BN_CLICKED)
          {
		    switch(guistate)
        {
		      case PIN_Entered:
  				/* insert signal PIN */
  				guistate = WaitCheckPIN;
          xSigIdNode = xGetSigIdNode("PIN");
          xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv); /* an xSignalNode is returned */

				  /* Set param1 to the pin value (PIN_t is an enum, pinCode is an int) */
          ((yPDP_PIN)(xInSignal))->Param1 = pinCode;
          SDL_Output(xInSignal, (xIdNode *)0);	
				  break;
		    case Normal:
			    /* Display "< Phone Book" in display" */
				  SetDlgItemText(hwnd, IDC_DISPLAY, "Phone Book >");
				  guistate = Menu_PhoneBook;
				  break;
			  case Conversation:
          SetDlgItemText(hwnd, IDC_DISPLAY, "TLOG");
          guistate = Normal;
				  /* Insert on_hook signal */
          xSigIdNode = xGetSigIdNode("on_hook");
          xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);
          SDL_Output(xInSignal, (xIdNode *)0);
				  break;
			  case Ringing:
				  /* Insert answer_call signal */
				  xSigIdNode = xGetSigIdNode("answer_call");
          xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);
          SDL_Output(xInSignal, (xIdNode *)0);
				  break;
			  case Menu_PhoneBook:
				  guistate = Menu_PhoneBook_John;
          /* Display "PhoneBook: John >" */
			    SetDlgItemText(hwnd, IDC_DISPLAY, "John >");
				  break;
			  case Menu_PhoneBook_John:
			    /* Insert dialing(Mobile_ID_t) signal */
				  xSigIdNode = xGetSigIdNode("dialing");
          xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);

				  /* Set param1 to the destination mobile (Mobile_ID_t is an enum) */
          ((yPDP_dialing)(xInSignal))->Param1 = 2;
          SDL_Output(xInSignal, (xIdNode *)0);
				  break;
			  case Menu_PhoneBook_Marie:
			    /* Insert dialing(Mobile_ID_t) signal */
				  xSigIdNode = xGetSigIdNode("dialing");
          xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);

				  /* Set param1 to the pin value (Mobile_ID_t is an enum) */
          ((yPDP_dialing)(xInSignal))->Param1 = 1;

          SDL_Output(xInSignal, (xIdNode *)0);
				  break;
			  case Menu_PhoneBook_LyonPizza:
				  /* Insert dialing(Mobile_ID_t) signal */
				  xSigIdNode = xGetSigIdNode("dialing");
          xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);

				  /* Set param1 to the pin value (Mobile_ID_t is an enum) */
          ((yPDP_dialing)(xInSignal))->Param1 = 5;

          SDL_Output(xInSignal, (xIdNode *)0);
				  break;
    		case Menu_PhoneBook_ParisPizza:
				  /* Insert dialing(Mobile_ID_t) signal */
				  xSigIdNode = xGetSigIdNode("dialing");
          xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);

				  /* Set param1 to the pin value (Mobile_ID_t is an enum) */
          ((yPDP_dialing)(xInSignal))->Param1 = 4;

          SDL_Output(xInSignal, (xIdNode *)0);
				  break;
			  case Menu_BillingReport:
          /* Insert askReport signal */
				  xSigIdNode = xGetSigIdNode("askReport");
          xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);
          SDL_Output(xInSignal, (xIdNode *)0);
				  break;
        }

      }
      break;

      case IDC_C:
		    if (HIWORD(wParam) == BN_CLICKED)
        {
			  switch(guistate)
        {
			    case Menu_PhoneBook:
		      case Menu_BillingReport:
				    guistate = Normal;
				    /* Clear the display */
				    SetDlgItemText(hwnd, IDC_DISPLAY, "TLOG");
			      break;
			    case ReportDuration:
			    case ReportPrice:
            guistate = Menu_BillingReport;
				    SetDlgItemText(hwnd, IDC_DISPLAY, "< Billing Report");
				    break;
		      case Menu_PhoneBook_John:
			    case Menu_PhoneBook_Marie:
		      case Menu_PhoneBook_LyonPizza:
			    case Menu_PhoneBook_ParisPizza:
				    guistate = Menu_PhoneBook;
				    /* Display "Phone Book >" */
				    SetDlgItemText(hwnd, IDC_DISPLAY, "PhoneBook >");
				    break;
			    case PIN_Entered:
				    guistate = Enter_PIN;
            /* Update display with "Enter PIN:" */
			      SetDlgItemText(hwnd, IDC_DISPLAY, "Enter PIN:");
			      break;
				
				  /* state Ringing is not considered for IDC_C, i.e. a call can not be rejected */

			    default:
				    break;
        }
      }
		  break;

	    case IDC_ONOFF:
        if (HIWORD(wParam) == BN_CLICKED)
        {
          dlgItem = GetDlgItem(hwnd, IDC_DISPLAY);
          hDc = GetDC(dlgItem);
          if (guistate == Off)
          {
            guistate = Enter_PIN; /* Should be changed to EnterPIN */

            SetBkMode(hDc, TRANSPARENT);
            SetDlgItemText(hwnd, IDC_DISPLAY, "Enter PIN:"); /* Operator displayed */
            SetDlgItemText(hwnd, IDC_ONOFF, "Off");

			      /* Insert signal "onKey" */
			      xSigIdNode = xGetSigIdNode("onKey");
            xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);
            SDL_Output(xInSignal, (xIdNode *)0);
          }
          else
          {
            guistate = Off;
            
            SetDlgItemText(hwnd, IDC_DISPLAY, "");
            SetDlgItemText(hwnd, IDC_ONOFF, "On");

            /* Disable base station combobox */
			      EnableWindow(GetDlgItem(hwnd, IDC_BASESTNCOMBO), FALSE);

		        /* Insert signal "offKey" */
			      xSigIdNode = xGetSigIdNode("offKey");
            xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);
            SDL_Output(xInSignal, (xIdNode *)0);
          }

        }
        break;

      case IDC_UP:
	      if (HIWORD(wParam) == BN_CLICKED)
        {
			    switch(guistate)
          {
			      case Menu_PhoneBook:
				      guistate = Menu_BillingReport;
			
				      /* Show "< Billing Report" */
				      SetDlgItemText(hwnd, IDC_DISPLAY, "< Billing Report");
				      break;
			      case Menu_PhoneBook_John:
              guistate = Menu_PhoneBook_Marie;
				      /* Show "Phone Book: < Marie >" */
				      SetDlgItemText(hwnd, IDC_DISPLAY, "< Marie >");
				      break;
			      case Menu_PhoneBook_Marie:
				      guistate = Menu_PhoneBook_LyonPizza;
				      /* Show "Phone Book: < LyonPizza >" */
				      SetDlgItemText(hwnd, IDC_DISPLAY, "< Lyon Pizza >");
				      break;
			      case Menu_PhoneBook_LyonPizza:
				      guistate = Menu_PhoneBook_ParisPizza;
			        /* Show "Phone Book: < ParisPizza" */
				      SetDlgItemText(hwnd, IDC_DISPLAY, "< Paris Pizza");
				      break;
			      case ReportDuration:
				      guistate = ReportPrice;
				      sprintf(billingText, "< Price: %4.2f", price);
				      SetDlgItemText(hwnd, IDC_DISPLAY, billingText);
				      break;

			      default:
				      break;
          }
        }
        break;

      case IDC_DOWN:
		    if (HIWORD(wParam) == BN_CLICKED)
        {
  			  switch(guistate)
          {
			       case Menu_BillingReport:
				       guistate = Menu_PhoneBook;
				       /* Show "Phone Book >" */
				       SetDlgItemText(hwnd, IDC_DISPLAY, "Phone Book >");
				       break;
			       case Menu_PhoneBook_Marie:
               guistate = Menu_PhoneBook_John;
				       /* Show "Phone Book: John >" */
				       SetDlgItemText(hwnd, IDC_DISPLAY, "John >");
				       break;
			       case Menu_PhoneBook_LyonPizza:
				       guistate = Menu_PhoneBook_Marie;
				       /* Show "Phone Book: < Marie >" */
				       SetDlgItemText(hwnd, IDC_DISPLAY, "< Marie >");
				       break;
			       case Menu_PhoneBook_ParisPizza:
				       guistate = Menu_PhoneBook_LyonPizza;
			         /* Show "Phone Book: < LyonPizza >" */
				       SetDlgItemText(hwnd, IDC_DISPLAY, "< Lyon Pizza >");
				       break;
	           case ReportPrice:
				       guistate = ReportDuration;
				       sprintf(billingText, "Duration: %d >", duration);
				       SetDlgItemText(hwnd, IDC_DISPLAY, billingText);
				       break;
			       default:
				       break;
          }
        }
        break;

      case IDC_BTN0:
		    if (HIWORD(wParam) == BN_CLICKED)
        {
			    if (guistate == Enter_PIN)
          {
			      guistate = PIN_Entered;
			      pinCode = 0;
            /* Update display with "Enter PIN: *" */
			      SetDlgItemText(hwnd, IDC_DISPLAY, "Enter PIN: *");
          }
        }
        break;
      case IDC_BTN1:
		    if (HIWORD(wParam) == BN_CLICKED)
        {
			    if (guistate == Enter_PIN)
          {
			      guistate = PIN_Entered;
			      pinCode = 1;
            /* Update display with "Enter PIN: *" */
			      SetDlgItemText(hwnd, IDC_DISPLAY, "Enter PIN: *");
          }
        }
        break;
      case IDC_BTN2:
	      if (HIWORD(wParam) == BN_CLICKED)
        {
			    if (guistate == Enter_PIN)
          {
			      guistate = PIN_Entered;
			      pinCode = 2;
            /* Update display with "Enter PIN: *" */
			      SetDlgItemText(hwnd, IDC_DISPLAY, "Enter PIN: *");
          }
        }
        break;
      case IDC_BTN3:
	      if (HIWORD(wParam) == BN_CLICKED)
        {
			    if (guistate == Enter_PIN)
          {
			      guistate = PIN_Entered;
			      pinCode = 3;
            /* Update display with "Enter PIN: *" */
			      SetDlgItemText(hwnd, IDC_DISPLAY, "Enter PIN: *");
          }
        }
        break;
      case IDC_BTN4:
		    if (HIWORD(wParam) == BN_CLICKED)
        {
      	  if (guistate == Enter_PIN)
          {
			      guistate = PIN_Entered;
			      pinCode = 4;
            /* Update display with "Enter PIN: *" */
			      SetDlgItemText(hwnd, IDC_DISPLAY, "Enter PIN: *");
          }
        }
        break;
      case IDC_BTN5:
	      if (HIWORD(wParam) == BN_CLICKED)
        {
      	  if (guistate == Enter_PIN)
          {
			      guistate = PIN_Entered;
			      pinCode = 5;
            /* Update display with "Enter PIN: *" */
			      SetDlgItemText(hwnd, IDC_DISPLAY, "Enter PIN: *");
          }
        }
        break;
      case IDC_BTN6:
		    if (HIWORD(wParam) == BN_CLICKED)
        {
      	  if (guistate == Enter_PIN)
          {
      			guistate = PIN_Entered;
			      pinCode = 6;
            /* Update display with "Enter PIN: *" */
      			SetDlgItemText(hwnd, IDC_DISPLAY, "Enter PIN: *");
          }
        }
        break;
      case IDC_BTN7:
  	    if (HIWORD(wParam) == BN_CLICKED)
        {
      	  if (guistate == Enter_PIN)
          {
      			guistate = PIN_Entered;
			      pinCode = 7;
            /* Update display with "Enter PIN: *" */
      			SetDlgItemText(hwnd, IDC_DISPLAY, "Enter PIN: *");
          }
        }
        break;
      case IDC_BTN8:
	      if (HIWORD(wParam) == BN_CLICKED)
        {
			    if (guistate == Enter_PIN)
          {
			      guistate = PIN_Entered;
			      pinCode = 8;
            /* Update display with "Enter PIN: *" */
			      SetDlgItemText(hwnd, IDC_DISPLAY, "Enter PIN: *");
          }
        }
        break;
      case IDC_BTN9:
	      if (HIWORD(wParam) == BN_CLICKED)
        {
			    if (guistate == Enter_PIN)
          {
			      guistate = PIN_Entered;
			      pinCode = 9;
            /* Update display with "Enter PIN: *" */
      			SetDlgItemText(hwnd, IDC_DISPLAY, "Enter PIN: *");
          }
        }
        break;

		  case IDC_BASESTNCOMBO:
        if (HIWORD(wParam) == CBN_SELCHANGE)
        {
          /* Get the new selection */
  		    currentBaseStation = SendMessage(GetDlgItem(hwnd, IDC_BASESTNCOMBO), CB_GETCURSEL, 0, 0);

          SendMessage(GetDlgItem(hwnd, IDC_BASESTNCOMBO), CB_GETLBTEXT, (WORD)currentBaseStation, (LONG)buffer);

          if (strcmp(buffer, "Paris11") == 0) currentBaseStation = 0;
          else if (strcmp(buffer, "Paris12") == 0) currentBaseStation = 1;
          else if (strcmp(buffer, "Lyon11") == 0) currentBaseStation = 2;
          else currentBaseStation = 3;
          
          /* Insert "BTSChanging" into the system */
  		    xSigIdNode = xGetSigIdNode("BTSchanging");
          xInSignal = xGetSignal(xSigIdNode, xNotDefPId, xEnv);
          
          /* Set Param1 to new BTS */
          ((yPDP_BTSchanging)(xInSignal))->Param1 = currentBaseStation;

          SDL_Output(xInSignal, (xIdNode *)0);
        }
	      break;

      default:
        break;
    }

    return TRUE;

	  case WM_TIMER:
	    if (wParam == IDT_DISPLAYTIMER)
      {
	      /* Reset the text and kill the timer */
  		  if (guistate == Enter_PIN)
	  	    SetDlgItemText(hwnd, IDC_DISPLAY, "Enter PIN: ");
	      else
		      SetDlgItemText(hwnd, IDC_DISPLAY, "TLOG");

		    KillTimer(hwnd, IDT_DISPLAYTIMER);
      }
	    return 0;

    case WM_HSCROLL:
      return 0;

    case WM_DESTROY:
      KillTimer(hwnd, IDT_DISPLAYTIMER);
      SDL_Halt();
      PostQuitMessage(0);
      return TRUE;

    case WM_CLOSE:
      DestroyWindow (hwnd);
      return TRUE;
  }

  return FALSE;
}


/*
  Method for separating signals to the GUI from signals to the TCP/IP module
  GUI signals are processed
  TCP/IP module signals are passed on to the TCP/IP module
*/
void xSendSignalToGUI(xSignalNode *xOutSignal, char *xSignalName)
{
  unsigned int mobileID, reportIndice;
  int i;
  int alternating = 0;

  /*
    Separate the signals in the displ signallist, as they should be handled by the GUI
  	Other signals go via the TCP/IP module
  */
  if (!strcmp(xSignalName, "badPIN"))
  {
	  /* Show "Bad PIN" message in text box. */
	  SetDlgItemText(hDialog, IDC_DISPLAY, "Bad PIN");
	  SetTimer(hDialog, IDT_DISPLAYTIMER, 2000, (TIMERPROC)NULL);
    guistate = Enter_PIN;
  }
  else if (!strcmp(xSignalName, "disable"))
  {
    /* Disable phone. Set text "Disabled". The phone is still on */
	  guistate = Disabled;
	  SetDlgItemText(hDialog, IDC_DISPLAY, "Disabled");
	  EnableWindow(GetDlgItem(hDialog, IDC_BASESTNCOMBO), FALSE);
  }
  else if (!strcmp(xSignalName, "initGUI"))
  {
    EnableWindow(GetDlgItem(hDialog, IDC_ONOFF), TRUE);
    /* set default basestation to Paris11 */
    SendMessage(GetDlgItem(hDialog,IDC_BASESTNCOMBO), CB_SETCURSEL, 0, 0);
  }
  else if (!strcmp(xSignalName, "rejected"))
  {
    /* Set text to "Call rejected" + timer */
    SetDlgItemText(hDialog, IDC_DISPLAY, "Call rejected");
    SetTimer(hDialog, IDT_DISPLAYTIMER, 2000, (TIMERPROC)NULL);
    guistate = Normal;
  }
  else if (!strcmp(xSignalName, "ring"))
  {
	  guistate = Ringing;
	  /* Set the display text to "Answer?" */
    SetDlgItemText(hDialog, IDC_DISPLAY, "Incoming Call");

    /* Make a simple ring signal to indicate that the phone is ringing */
    for (i=0; i < 50; i++)
    {
      if (alternating)
        Beep(1000, 10);
      else
        Beep(1200, 10);

      alternating = !alternating;
    }
  }
  else if (!strcmp(xSignalName, "unlock"))
  {
    /* Set text to PIN OK + set timer */
	  SetDlgItemText(hDialog, IDC_DISPLAY, "PIN OK");
    /* Enable base station combobox */
	  EnableWindow(GetDlgItem(hDialog, IDC_BASESTNCOMBO), TRUE);
    SetTimer(hDialog, IDT_DISPLAYTIMER, 2000, (TIMERPROC)NULL);
    guistate = Normal;
  }
  else if (!strcmp(xSignalName, "convers"))
  {
    /* Set text to "Conversation" */
	  guistate = Conversation;
	  SetDlgItemText(hDialog, IDC_DISPLAY, "Conversation");
  }
  else if (!strcmp(xSignalName, "busy"))
  {
    /* set display text to "Busy" + timer */
	  SetDlgItemText(hDialog, IDC_DISPLAY, "Busy");
	  SetTimer(hDialog, IDT_DISPLAYTIMER, 2000, (TIMERPROC)NULL);
	  guistate = Normal;  
  }
  else if (!strcmp(xSignalName, "unreachable"))
  {
    /* set display text to "Unreachable" + timer */
	  SetDlgItemText(hDialog, IDC_DISPLAY, "Unreachable");
	  SetTimer(hDialog, IDT_DISPLAYTIMER, 2000, (TIMERPROC)NULL);
	  guistate = Normal;
  }
  else if (!strcmp(xSignalName, "giveReport"))
  {
    /* Report information to display */
	  guistate = ReportDuration;

    reportIndice = ((yPDP_giveReport)(*xOutSignal))->Param1.nb_com - 1; /* latest call = number of calls - 1 */
    duration =    (((yPDP_giveReport)(*xOutSignal))->Param1).bil.A[reportIndice].duration;
    price =       (((yPDP_giveReport)(*xOutSignal))->Param1).bil.A[reportIndice].price;

	  sprintf(billingText, "Duration: %d >", duration);
	  SetDlgItemText(hDialog, IDC_DISPLAY, billingText);
  }
  else
	  /* Send the signal via the TCP/IP interface */
	  xSendSignal(xOutSignal, xSignalName);

  return;
}

#endif