/*\
 *  Izbor elementov iz Acad baze
 *  $Id:$
\*/

#include "entity.h"


/*
 * Vrne naslov elementa v extended entity data podro"cju
 * specificiranem s stringom, "ce ga ne najde, vrne NULL
 * Ce je zajetih vec aplikacij v X data potem vrne prvi string,
 * ki ga najde
 */
union ads_u_val *
getXdata (struct resbuf * rb, const char *name)
{
  while (rb != NULL)
    {
      if (rb->restype == 1001)
	      {
	        rb = rb->rbnext;
	        while (rb != NULL)
	          {
		          if (rb->restype == 1000)
		          if (strcmp (name, rb->resval.rstring) == 0)
		            {
		              rb = rb->rbnext;
		              return &(rb->resval);
		            }
		          rb = rb->rbnext;
	          }
            // ads_printf("Warning: getXdata(rb, %s) not found!\n", name );

            return NULL;
	      }
      rb = rb->rbnext;
    }
  return NULL;
}


/*
 * Vrne naslov vrednosti elementa v data podro"cju
 * specificiranem s selektorjem dxfval ce ga ne najde, vrne NULL
 *
 * Primer uporabe: assoc(10, rb)->rpoint 
 */
union ads_u_val *
assoc (short dxfval, struct resbuf * rb)
{
  while (rb != NULL)
    {
      if (rb->restype == dxfval)
	      return &(rb->resval);
      rb = rb->rbnext;
    }
  return NULL;
}



/*
 * Za podan string preveri ali obstaja TAG v Xdata podrocju
 * s takim imenom
 */
int isA(const char *name, struct resbuf *rb)
{
  union ads_u_val *xp = getXdata(rb, "TAG");
  if (xp == NULL)
    return 0;
  int status = !strcmp(xp->rstring, name);
  return status;
}



/////////////////////////////////////////////////////////////////

/** {duh} **/
Entity::Entity()
{
  rb = NULL;
  hasXdata = 0;
}

/** {duh} **/
Entity::Entity(ads_name name)
{
  Entity::name[0] = name[0];
  Entity::name[1] = name[1];
  rb = NULL;
  hasXdata = 0;
}

/** {duh} **/
Entity::~Entity()
{
  if (rb)  ads_relrb(rb);
}


/**
 ** Shrani gradnik nazaj v bazo ACAD. Ta sinhronizacija je potrebna le
 ** ce smo popravljali notranje podatke gradnika tj. resbuf
 **/
Entity::Modify()
{
  return (ads_entmod(rb));
}

/**
 ** Izbere gradnik v ACAD-u
 **/
int Entity::Pick(char *prompt)
{
  int status;
  status = ads_entsel(prompt, name, pickPoint);
  if (status != RTNORM)
    return (status);
  return (RTNORM);
}

/**
 ** Vrne /i/-to (x, y, z) koordinato gradnika
 **/
ads_real Entity::GetPoint(int i)
{
  if (!rb)
    Get();
  return assoc(10, rb)->rpoint[i];
}

/** {duh} **/
void Entity::GetHandle()
{
  if (!rb)
    Get();
  handle = assoc(5, rb)->rstring;
}


/**
 ** Poisce prvi zapis za naziv vozla v podro"cju Cybernet
 **/
int Entity::GetNodeName()
{
  if (!rb)
    Get();

  if (rb && hasXdata)
    {
      char *nodestr[] = { "NODE_#", "DNODE_#", "UNODE_#", "CNODE_#"};
      union ads_u_val *entity;
      for (short i = 0; i < 4; i++)
        {
          entity = getXdata(rb, nodestr[i]);
          if (entity)

            {
              if (nodestr[i][0] != 'N')
                {
                  nodeName =  nodestr[i];
                  nodeName += entity->rstring;
                }
              else
                nodeName = entity->rstring;
              return 0;
            }
        }
    }
  nodeName = "";
  return 1;
}

/** {duh} **/
Strings Entity::GetDXFName()
{
  if (!rb)
    Get();
  DXFname = assoc(0, rb)->rstring;
  return DXFname;
}

/** {duh} **/
Strings Entity::GetLayer()
{
  if (!rb)
    Get();
  layer = assoc(8, rb)->rstring;
  return layer;
}

/** {duh} **/
void Entity::GetTag()
{
  if (!rb)
    Get();
  tag = getXdata(rb, "TAG")->rstring;
}


/** {duh} **/
struct resbuf * Entity::GetResBuf()
{
  if (!rb)
    Get();
  return rb;
}


/**
 ** Iz baze ACAD vzame /resbuf/ za gradnik registriran z name in
 ** po moznosti z registriranimi aplikacijami.
 **/
int Entity::Get()
{
  if (rb)
    ads_relrb(rb);

  rb = ads_entgetx(name, apps);

  if (rb == NULL)
    return RTERROR;

  if (assoc(1001, rb))
    {
      hasXdata = 1;
    }
  return (RTNORM);
}

int Entity::Get(ads_name entname)
{
  name[0] = entname[0];
  name[1] = entname[1];
  return Get();
}


/**
 ** Sprosti /resbuf/ ki ga zaseda gradnik
 **/
void Entity::Release()
{
  if (rb)
    {
      ads_relrb(rb);
      rb = NULL;
    }
}

/**
 ** Doda aplikacijo registriranim aplikacijam za vse gradnike ACAD, tako
 ** da lahko funkcije za XDATA (ads_entgetx) dostopajo do podatkov
 ** izbranih aplikacij.
 **/
void Entity::Register(const char *appName)
{
  struct resbuf *app;

  app = ads_buildlist(RTSTR, appName, NULL);
  app->rbnext = apps;
  apps = app;
}

/**
 ** Zbrise vse registrirane aplikacije
 **/
void Entity::UnRegister()
{
  if (apps)
    ads_relrb(apps);
  apps = NULL;
}

/**
 ** V XDATA podrocju pogleda, ce /tag/ ze obstaja in zamenja obstojeco
 ** vrednost z /value/. Ce /tag/ ne obstaja, ga naredi skupaj z novo
 ** vrednostjo /value/ na zacetku prve registrirane aplikacije /appName/
 ** za Entity.
 **/
Entity::SaveTag(const char *tag, const char *value, const char *appName)
{
  union ads_u_val *tagVal;
  if (!rb)
    Get();
  if ((tagVal = getXdata(rb, tag)) == NULL)
    {
      for (struct resbuf *srb = rb; srb->rbnext; srb = srb->rbnext)
        {
          if (srb->restype == 1001
		          && strcmp (appName, srb->resval.rstring) == 0)
	          {
              struct resbuf *etag;
              etag = ads_buildlist(1000, tag, 1000, value, NULL);
              if (etag == NULL)
                return RTERROR;
              etag->rbnext->rbnext = srb->rbnext;
              srb->rbnext = etag;
              return RTNORM;
	          }
        }
      srb->rbnext = ads_buildlist(1001, appName, 1000, tag, 1000, value, NULL);
      if (srb->rbnext == NULL)
        return RTERROR;
    }
  else
    {
      if (value == NULL)
        tagVal->rstring =  (char *) calloc(1,1);
      else
        {
           char *buff;
           buff = (char *)realloc(tagVal->rstring, strlen(value) + 1);
           if (buff == NULL)
              return RTERROR;
           else
            {
              tagVal->rstring = buff;
              strcpy(tagVal->rstring, value);
            }
        }
      if (tagVal->rstring == NULL)
        return RTERROR;
    }
  return RTNORM;
}

/**
 ** Shrani celostevilcno vrednost
 **/
Entity::SaveTag(const char *tag, int value, const char *appName)
{
  union ads_u_val *tagVal;
  if (!rb)
    Get();
  if ((tagVal = getXdata(rb, tag)) == NULL)
    {
      for (struct resbuf *srb = rb; srb->rbnext; srb = srb->rbnext)
        {
          if (srb->restype == 1001
		          && strcmp (appName, srb->resval.rstring) == 0)
	          {
              struct resbuf *etag;
              etag = ads_buildlist(1000, tag, 1071, value, NULL);
              etag->rbnext->rbnext = srb->rbnext;
              srb->rbnext = etag;
              return RTNORM;
	          }
        }
      srb->rbnext = ads_buildlist(1001, appName, 1000, tag, 1071, value, NULL);
      if (srb->rbnext == NULL)
        return RTERROR;
    }
  else
    {
      tagVal->rlong = value;
    }
  return RTNORM;
}

/**
 ** Shrani realno vrednost
 **/
Entity::SaveTag(const char *tag, ads_real value, const char *appName)
{
  union ads_u_val *tagVal;
  if (!rb)
    Get();
  if ((tagVal = getXdata(rb, tag)) == NULL)
    {
      for (struct resbuf *srb = rb; srb->rbnext; srb = srb->rbnext)
        {
          if (srb->restype == 1001
		          && strcmp (appName, srb->resval.rstring) == 0)
	          {
              struct resbuf *etag;
              etag = ads_buildlist(1000, tag, 1040, value, NULL);
              etag->rbnext->rbnext = srb->rbnext;
              srb->rbnext = etag;
              return RTNORM;
	          }
        }
      srb->rbnext = ads_buildlist(1001, appName, 1000, tag, 1040, value, NULL);
      if (srb->rbnext == NULL)
        return RTERROR;
    }
  else
    {
      tagVal->rreal = value;
    }
  return RTNORM;
}


/**
 ** Poisce zapis za cev v extended entity podrocju, ce le to obstaja
 ** Vrne stevilko cevi; ce ne najde zapisa, vrne 0
 **/
long Entity::PipeNum()
{
  if (rb && hasXdata)
    {
      union ads_u_val *pipe;
      pipe = getXdata(rb, "PIPE_#");
      if (pipe)
        return pipe->rlong;
      pipe = getXdata(rb, "UPIPE_#");
      if (pipe)
        return pipe->rlong;
      pipe = getXdata(rb, "DPIPE_#");
      if (pipe)
        return pipe->rlong;
    }
  return 0;
}


struct resbuf * Entity::apps = NULL;






syntax highlighted by Code2HTML, v. 0.9.1