dwg_find_table_extname (Dwg_Data *restrict dwg, Dwg_Object *restrict obj)
{
  char *name;
  Dwg_Object *xdic;
  Dwg_Object_DICTIONARY *_xdic;
  Dwg_Object_Ref *xdicref;
  Dwg_Object *xrec = NULL;
  Dwg_Object_XRECORD *_xrec;
  Dwg_Resbuf *xdata;
  BITCODE_BL i;

  // (GH #167) via DICTIONARY ACAD_XREC_ROUNDTRIP to XRECORD EXTNAMES
  if (!dwg_obj_is_table (obj))
    return NULL;
  // HACK: we can guarantee that the table name is always the first field. See
  // dwg_obj_table_get_name().
  name = obj->tio.object->tio.LAYER->name;
  xdicref = obj->tio.object->xdicobjhandle;
  if (!xdicref)
    return NULL;
  xdic = dwg_ref_object (dwg, xdicref);
  if (!xdic || xdic->type != DWG_TYPE_DICTIONARY)
    return NULL;
  _xdic = xdic->tio.object->tio.DICTIONARY;
  if (_xdic->numitems < 1 || !_xdic->texts[0])
    return NULL;
  if (xdic->tio.object->ownerhandle->absolute_ref != obj->handle.value)
    return NULL;
  for (i = 0; i < _xdic->numitems; i++)
    {
      if (strEQc (_xdic->texts[i], "ACAD_XREC_ROUNDTRIP"))
        break;
    }
  if (i == _xdic->numitems) // not found
    return NULL;
  xrec = dwg_ref_object (dwg, _xdic->itemhandles[i]);
  if (!xrec || !is_extnames_xrecord (dwg, xrec, xdic))
    return NULL;

  _xrec = xrec->tio.object->tio.XRECORD;
  xdata = _xrec->xdata;
  xdata = xdata->nextrb;
  if (xdata->type == 1) // pairs of 1: old name, 2: new name
    {
      // step to the matching name
    cmp:
      if (!xdata_string_match (dwg, xdata, 1, name))
        {
          xdata = xdata->nextrb;
          while (xdata && xdata->type != 1 && xdata->type != 102)
            xdata = xdata->nextrb;
          if (xdata)
            goto cmp;
        }
      if (!xdata)
        return NULL;
      xdata = xdata->nextrb;
      if (xdata->type == 2) // new name
        {
          if (!IS_FROM_TU_DWG (dwg))
            return xdata->value.str.u.data;
          else
            return (char *)xdata->value.str.u.wdata;
        }
    }

  return NULL;
}
dwg_find_table_extname (Dwg_Data *restrict dwg, Dwg_Object *restrict obj)
{
  char *name;
  Dwg_Object *xdic;
  Dwg_Object_DICTIONARY *_xdic;
  Dwg_Object_Ref *xdicref;
  Dwg_Object *xrec = NULL;
  Dwg_Object_XRECORD *_xrec;
  Dwg_Resbuf *xdata;
  BITCODE_BL i;

   
  if (!dwg_obj_is_table (obj))
    return NULL;
   
   
  name = obj->tio.object->tio.LAYER->name;
  xdicref = obj->tio.object->xdicobjhandle;
  if (!xdicref)
    return NULL;
  xdic = dwg_ref_object (dwg, xdicref);
  if (!xdic || xdic->type != DWG_TYPE_DICTIONARY)
    return NULL;
  _xdic = xdic->tio.object->tio.DICTIONARY;
  if (_xdic->numitems < 1 || !_xdic->texts[0])
    return NULL;
  if (xdic->tio.object->ownerhandle->absolute_ref != obj->handle.value)
    return NULL;
  for (i = 0; i < _xdic->numitems; i++)
    {
      if (strEQc (_xdic->texts[i], "ACAD_XREC_ROUNDTRIP"))
        break;
    }
  if (i == _xdic->numitems)  
    return NULL;
  xrec = dwg_ref_object (dwg, _xdic->itemhandles[i]);
  if (!xrec || !is_extnames_xrecord (dwg, xrec, xdic))
    return NULL;

  _xrec = xrec->tio.object->tio.XRECORD;
  xdata = _xrec->xdata;
  xdata = xdata->nextrb;
  if (xdata->type == 1)  
    {
       
    cmp:
      if (!xdata_string_match (dwg, xdata, 1, name))
        {
          xdata = xdata->nextrb;
          while (xdata && xdata->type != 1 && xdata->type != 102)
            xdata = xdata->nextrb;
          if (xdata)
            goto cmp;
        }
      if (!xdata)
        return NULL;
      xdata = xdata->nextrb;
      if (xdata->type == 2)  
        {
          if (!IS_FROM_TU_DWG (dwg))
            return xdata->value.str.u.data;
          else
            return (char *)xdata->value.str.u.wdata;
        }
    }

  return NULL;
}