#include "XtkScreen.h"

#include "misc.h"
#include "MsgQ.h"

XtkScreen::XtkScreen(int argc, char **argv)
  : X11Screen(argc, argv)
{;}

XtkScreen::~XtkScreen()
{ ; }

typedef struct
{
  int which;
  unsigned long milli;
  XtAppContext app;
  HandlerFunc timerFunc;
  XtIntervalId* timerId;
} TimerData;

void *TimerClientData;
// End of timer
static void TimerNotify(XtPointer clt, XtIntervalId* /*id*/)
{
  TimerData* data = (TimerData*)clt;

  // call registered function
  data->timerFunc(data->which, TimerClientData);
  
  // reinstall timeout (blinking active unit)
  *data->timerId = XtAppAddTimeOut(data->app, data->milli, TimerNotify, clt);
}

// start timer `which'
void XtkScreen::StartTimer(int which, unsigned long milli, HandlerFunc func, void *client_data)
{
  if (which != 0) return;
  TimerData* clt = (TimerData*)malloc(sizeof(TimerData));
  
  Timers[which] = func;
  clt->which = which;
  clt->milli = milli;
  clt->app = this->app;
  clt->timerFunc = this->Timers[which];
  clt->timerId = &(timerId[which]);
  TimerClientData = client_data;
  timerId[which] = XtAppAddTimeOut(app, milli, TimerNotify, (XtPointer)clt);
}

void XtkScreen::StopTimer(int which)
{
  if (which != 0) return;
  XtRemoveTimeOut(timerId[which]);
  // FIXME: does Xt frees clt data ?
}

// Handler for incoming connections
// got data, read the queue and hand it to the guy who wants it
void ReadNotify(XtPointer clt, int* fd_p, XtInputId* /*id*/)
{
  extern MsgQ *RecvQ(int);
  ReadHandler *ptr = ((XtkScreen*)clt)->readHandlers[*fd_p];
  if (ptr == NULL) return;
  MsgQ *q = NULL;
  if (ptr->q)
    q = RecvQ(*fd_p);
  // FIXME: verify ?
  (*ptr->func)(q, *fd_p, ptr->info);
  return;
}

// add Xt handler for file reading
void XtkScreen::AddReadNotify(int fd, readNotifyFunc func, int info, int q)
{
  ReadHandler *ptr = new ReadHandler;
  readHandlers[fd] = ptr;
  ptr->fd = fd;
  ptr->func = func;
  ptr->q = q;
  ptr->info = info;
  XtAppAddInput(app, fd, (XtPointer)XtInputReadMask, ReadNotify, (XtPointer)this);
}

