# include "Ximage.h"
# include <unistd.h>
# include <errno.h>

# define SCAN \
status = read (sock, buffer, 16); \
buffer[16] = 0; \
sscanf (buffer, "%*s %d", &Nbytes); \
status = read (sock, buffer, Nbytes); \
buffer[status] = 0;

int LoadObject () {
  
  char buffer[1024];
  int status, N, Nbytes;
  Layout *layout;

  layout = &section[TheSection];
  
  fcntl (sock, F_SETFL, !O_NONBLOCK);  
  
  N = layout[0].Nobjects;
  layout[0].Nobjects ++;
  REALLOCATE (layout[0].objects, Gobjects, layout[0].Nobjects);
  layout[0].objects[N].x = layout[0].objects[N].y = layout[0].objects[N].z = (float *) NULL;
  layout[0].objects[N].dxm = layout[0].objects[N].dxp = (float *) NULL;
  layout[0].objects[N].dym = layout[0].objects[N].dyp = (float *) NULL;
  
  SCAN;
  sscanf (buffer, "%d %d %d %d %d %d %d %lf %lf",
	  &layout[0].objects[N].Npts, &layout[0].objects[N].style, 
	  &layout[0].objects[N].ptype, &layout[0].objects[N].ltype, 
	  &layout[0].objects[N].etype, &layout[0].objects[N].ebar, 
	  &layout[0].objects[N].color, 
	  &layout[0].objects[N].lweight, &layout[0].objects[N].size);
  
  if (DEBUG) fprintf (stderr, "%d %d %d %d %d %d %d %lf %lf\n",
	  layout[0].objects[N].Npts, layout[0].objects[N].style, 
	  layout[0].objects[N].ptype, layout[0].objects[N].ltype, 
	  layout[0].objects[N].etype, layout[0].objects[N].ebar, 
	  layout[0].objects[N].color, 
	  layout[0].objects[N].lweight, layout[0].objects[N].size);
  
  /* force valid ranges */
  if ((layout[0].objects[N].color > NGRAPHCOLORS) || (layout[0].objects[N].color < 0))
    layout[0].objects[N].color = 0;

  SCAN;
  sscanf (buffer, "%lf %lf %lf %lf",
	  &layout[0].objects[N].x0, &layout[0].objects[N].x1, 
	  &layout[0].objects[N].y0, &layout[0].objects[N].y1);
  
  fcntl (sock, F_SETFL, O_NONBLOCK);  
  
  if (!LoadVectorData (layout, N, "x")) {
    FreeObjectData (&layout[0].objects[N]);
    layout[0].Nobjects --;
    REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
  }
    
  if (!LoadVectorData (layout, N, "y")) {
    FreeObjectData (&layout[0].objects[N]);
    layout[0].Nobjects --;
    REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
  }
  if (layout[0].objects[N].size < 0.0) {
    if (!LoadVectorData (layout, N, "z")) {
      FreeObjectData (&layout[0].objects[N]);
      layout[0].Nobjects --;
      REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
    }
  }
  if (layout[0].objects[N].etype & 0x01) {
    if (!LoadVectorData (layout, N, "dym")) {
      FreeObjectData (&layout[0].objects[N]);
      layout[0].Nobjects --;
      REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
    }
    if (!LoadVectorData (layout, N, "dyp")) {
      FreeObjectData (&layout[0].objects[N]);
      layout[0].Nobjects --;
      REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
    }
  }
  if (layout[0].objects[N].etype & 0x02) {
    if (!LoadVectorData (layout, N, "dxm")) {
      FreeObjectData (&layout[0].objects[N]);
      layout[0].Nobjects --;
      REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
    }
    if (!LoadVectorData (layout, N, "dxp")) {
      FreeObjectData (&layout[0].objects[N]);
      layout[0].Nobjects --;
      REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
    }
  }

  if (DEBUG) fprintf (stderr, "loaded %d objects, using object %d\n", layout[0].objects[N].Npts, N);

  DrawObjectN (layout, &layout[0].objects[layout[0].Nobjects-1]);
  FlushDisplay ();

  return (TRUE);
  
}

/* load data for the named component */
int LoadVectorData (Layout *layout, int N, char *type) {
  
  int Npts, Ninpts, status, Ntry;
  int bytes_left;
  char *buff;

  Npts = layout[0].objects[N].Npts;
  status = 1;
  if (!strcmp (type, "x")) {
    ALLOCATE (layout[0].objects[N].x, float, MAX (1, Npts));
    buff = (char *) layout[0].objects[N].x;
  }
  if (!strcmp (type, "y")) {
    ALLOCATE (layout[0].objects[N].y, float, MAX (1, Npts));
    buff = (char *) layout[0].objects[N].y;
  }
  if (!strcmp (type, "z")) {
    ALLOCATE (layout[0].objects[N].z, float, MAX (1, Npts));
    buff = (char *) layout[0].objects[N].z;
  }
  if (!strcmp (type, "dxm")) {
    ALLOCATE (layout[0].objects[N].dxm, float, MAX (1, Npts));
    buff = (char *) layout[0].objects[N].dxm;
  }
  if (!strcmp (type, "dxp")) {
    ALLOCATE (layout[0].objects[N].dxp, float, MAX (1, Npts));
    buff = (char *) layout[0].objects[N].dxp;
  }
  if (!strcmp (type, "dym")) {
    ALLOCATE (layout[0].objects[N].dym, float, MAX (1, Npts));
    buff = (char *) layout[0].objects[N].dym;
  }
  if (!strcmp (type, "dyp")) {
    ALLOCATE (layout[0].objects[N].dyp, float, MAX (1, Npts));
    buff = (char *) layout[0].objects[N].dyp;
  }

  bytes_left = Npts*sizeof (float);

  Ntry = 0;
  if (DEBUG) fprintf (stderr, "starting vector load\n");
  Ninpts = 0;
  while (bytes_left > 0) {
    status = read (sock, buff, bytes_left);
    if (DEBUG) fprintf (stderr, "status: %d, %d\n", status, bytes_left);
    if (status == 0) {  /* No more pipe */
      fprintf (stderr, "error: pipe closed\n");
      return (FALSE);
    }
    if (status != -1) { /* pipe has data */
      Ninpts += status;
      bytes_left -= status;
      buff = (char *)(buff + status);
      Ntry = 0;
      continue;
    }
    if (errno == EAGAIN) {
      Ntry ++;
      if (Ntry > 100) {
	fprintf (stderr, "kapa communication error\n");
	return (FALSE);
      }
      usleep (10000);
      continue;
    }
    perror ("kapa load");
  }
  if (Ninpts != Npts*sizeof(float)) {  
    fprintf (stderr, "error: expected %d bytes, but got only %d\n", Ninpts, Npts*sizeof(float));
    return (FALSE);
  }
  if (DEBUG) fprintf (stderr, "done vector load\n");
  return (TRUE);

}

FreeObjectData (Gobjects *object) {

  if (object[0].x != (float *) NULL) free (object[0].x);
  if (object[0].y != (float *) NULL) free (object[0].y);
  if (object[0].z != (float *) NULL) free (object[0].z);

  if (object[0].dxm != (float *) NULL) free (object[0].dxm);
  if (object[0].dxp != (float *) NULL) free (object[0].dxp);
  if (object[0].dym != (float *) NULL) free (object[0].dym);
  if (object[0].dyp != (float *) NULL) free (object[0].dyp);
}

