OGRSpatialReference *OGRGeoconceptLayer::GetSpatialRef()

{
    GCExportFileH* hGXT= GetSubTypeGCHandle_GCIO(_gcFeature);
    if( !hGXT ) return NULL;
    GCExportFileMetadata* Meta= GetGCMeta_GCIO(hGXT);
    if( !Meta ) return NULL;
    return (OGRSpatialReference*)GetMetaSRS_GCIO(Meta);
}
void OGRGeoconceptLayer::SetSpatialRef( OGRSpatialReference *poSpatialRef )

{
    GCSysCoord* os, *ns;
    OGRSpatialReference* poSRS= GetSpatialRef();
    GCExportFileH* hGXT;
    GCExportFileMetadata* Meta;
    /*-----------------------------------------------------------------
     * Keep a copy of the OGRSpatialReference...
     * Note: we have to take the reference count into account...
     *----------------------------------------------------------------*/
    if( poSRS && poSRS->Dereference() == 0) delete poSRS;

    if( !poSpatialRef ) return;

    poSRS= poSpatialRef->Clone();
    if( !(hGXT= GetSubTypeGCHandle_GCIO(_gcFeature)) ) return;
    if( !(Meta= GetGCMeta_GCIO(hGXT)) ) return;
    os= GetMetaSysCoord_GCIO(Meta);
    ns= OGRSpatialReference2SysCoord_GCSRS((OGRSpatialReferenceH)poSRS);

    if( os && ns &&
        GetSysCoordSystemID_GCSRS(os)!=-1 &&
        (
          GetSysCoordSystemID_GCSRS(os)!=GetSysCoordSystemID_GCSRS(ns) ||
          GetSysCoordTimeZone_GCSRS(os)!=GetSysCoordTimeZone_GCSRS(ns)
        )
      )
    {
      CPLError( CE_Warning, CPLE_AppDefined,
                "Can't change SRS on Geoconcept layers.\n" );
      return;
    }

    if( os ) DestroySysCoord_GCSRS(&os);
    SetMetaSysCoord_GCIO(Meta, ns);
    SetMetaSRS_GCIO(Meta, (OGRSpatialReferenceH)poSRS);
    return;
}
OGRLayer *OGRGeoconceptDataSource::CreateLayer( const char * pszLayerName,
                                                OGRSpatialReference *poSRS /* = NULL */,
                                                OGRwkbGeometryType eType /* = wkbUnknown */,
                                                char ** papszOptions /* = NULL */ )

{
    GCTypeKind gcioFeaType;
    GCDim gcioDim;
    OGRGeoconceptLayer *poFile= NULL;
    const char *pszFeatureType; 
    char **ft;
    int iLayer;
    char pszln[512];

    if( _hGXT == NULL )
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "Internal Error : null datasource handler."
                );
        return NULL;
    }

    if( poSRS == NULL && !_bUpdate)
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "SRS is mandatory of creating a Geoconcept Layer."
                );
        return NULL;
    }

    /*
     * pszLayerName Class.Subclass if -nln option used, otherwise file name
     */
    if( !(pszFeatureType = CSLFetchNameValue(papszOptions,"FEATURETYPE")) )
    {
      if( !pszLayerName || !strchr(pszLayerName,'.') )
      {
        snprintf(pszln,511,"%s.%s", pszLayerName? pszLayerName:"ANONCLASS",
                                    pszLayerName? pszLayerName:"ANONSUBCLASS");
        pszln[511]= '\0';
        pszFeatureType= pszln;
      }
      else
        pszFeatureType= pszLayerName;
    }

    if( !(ft= CSLTokenizeString2(pszFeatureType,".",0)) ||
        CSLCount(ft)!=2 )
    {
      CSLDestroy(ft);
      CPLError( CE_Failure, CPLE_AppDefined,
                "Feature type name '%s' is incorrect."
                "Correct syntax is : Class.Subclass.",
                pszFeatureType );
      return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Figure out what type of layer we need.                          */
/* -------------------------------------------------------------------- */
    gcioDim= v2D_GCIO;
    if( eType == wkbUnknown )
        gcioFeaType = vUnknownItemType_GCIO;
    else if( eType == wkbPoint )
        gcioFeaType = vPoint_GCIO;
    else if( eType == wkbLineString )
        gcioFeaType = vLine_GCIO;
    else if( eType == wkbPolygon )
        gcioFeaType = vPoly_GCIO;
    else if( eType == wkbMultiPoint )
        gcioFeaType = vPoint_GCIO;
    else if( eType == wkbMultiLineString )
        gcioFeaType = vLine_GCIO;
    else if( eType == wkbMultiPolygon )
        gcioFeaType = vPoly_GCIO;
    else if( eType == wkbPoint25D )
    {
        gcioFeaType = vPoint_GCIO;
        gcioDim= v3DM_GCIO;
    }
    else if( eType == wkbLineString25D )
    {
        gcioFeaType = vLine_GCIO;
        gcioDim= v3DM_GCIO;
    }
    else if( eType == wkbPolygon25D )
    {
        gcioFeaType = vPoly_GCIO;
        gcioDim= v3DM_GCIO;
    }
    else if( eType == wkbMultiPoint25D )
    {
        gcioFeaType = vPoint_GCIO;
        gcioDim= v3DM_GCIO;
    }
    else if( eType == wkbMultiLineString25D )
    {
        gcioFeaType = vLine_GCIO;
        gcioDim= v3DM_GCIO;
    }
    else if( eType == wkbMultiPolygon25D )
    {
        gcioFeaType = vPoly_GCIO;
        gcioDim= v3DM_GCIO;
    }
    else
    {
        CSLDestroy(ft);
        CPLError( CE_Failure, CPLE_NotSupported,
                  "Geometry type of '%s' not supported in Geoconcept files.",
                  OGRGeometryTypeToName(eType) );
        return NULL;
    }

    /*
     * As long as we use the CONFIG, creating a layer implies the
     * layer name to exist in the CONFIG as "Class.Subclass".
     * Removing the CONFIG, implies on-the-fly-creation of layers...
     */
    if( _nLayers > 0 )
      for( iLayer= 0; iLayer<_nLayers; iLayer++)
      {
        poFile= (OGRGeoconceptLayer*)GetLayer(iLayer);
        if( EQUAL(poFile->GetLayerDefn()->GetName(),pszFeatureType) )
        {
          break;
        }
        poFile= NULL;
      }
    if( !poFile )
    {
      GCSubType* aSubclass= NULL;
      GCExportFileMetadata* m;

      if( !(m= GetGCMeta_GCIO(_hGXT)) )
      {
        if( !(m= CreateHeader_GCIO()) )
        {
          CSLDestroy(ft);
          return NULL;
        }
        SetMetaExtent_GCIO(m, CreateExtent_GCIO(HUGE_VAL,HUGE_VAL,-HUGE_VAL,-HUGE_VAL));
        SetGCMeta_GCIO(_hGXT, m);
      }
      if( FindFeature_GCIO(_hGXT, pszFeatureType) )
      {
        CSLDestroy(ft);
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Layer '%s' already exists.",
                  pszFeatureType );
        return NULL;
      }
      if( !AddType_GCIO(_hGXT, ft[0], -1L) )
      {
        CSLDestroy(ft);
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Failed to add layer '%s'.",
                  pszFeatureType );
        return NULL;
      }
      if( !(aSubclass= AddSubType_GCIO(_hGXT, ft[0], ft[1], -1L, gcioFeaType, gcioDim)) )
      {
        CSLDestroy(ft);
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Failed to add layer '%s'.",
                  pszFeatureType );
        return NULL;
      }
      /* complete feature type with private fields : */
      AddSubTypeField_GCIO(_hGXT, ft[0], ft[1], -1L, kIdentifier_GCIO, -100, vIntFld_GCIO, NULL, NULL);
      AddSubTypeField_GCIO(_hGXT, ft[0], ft[1], -1L, kClass_GCIO, -101, vMemoFld_GCIO, NULL, NULL);
      AddSubTypeField_GCIO(_hGXT, ft[0], ft[1], -1L, kSubclass_GCIO, -102, vMemoFld_GCIO, NULL, NULL);
      AddSubTypeField_GCIO(_hGXT, ft[0], ft[1], -1L, kName_GCIO, -103, vMemoFld_GCIO, NULL, NULL);
      AddSubTypeField_GCIO(_hGXT, ft[0], ft[1], -1L, kNbFields_GCIO, -104, vIntFld_GCIO, NULL, NULL);
      AddSubTypeField_GCIO(_hGXT, ft[0], ft[1], -1L, kX_GCIO, -105, vRealFld_GCIO, NULL, NULL);
      AddSubTypeField_GCIO(_hGXT, ft[0], ft[1], -1L, kY_GCIO, -106, vRealFld_GCIO, NULL, NULL);
      /* user's fields will be added with Layer->CreateField() method ... */
      switch( gcioFeaType )
      {
        case vPoint_GCIO :
          break;
        case vLine_GCIO  :
          AddSubTypeField_GCIO(_hGXT, ft[0], ft[1], -1L, kXP_GCIO, -107, vRealFld_GCIO, NULL, NULL);
          AddSubTypeField_GCIO(_hGXT, ft[0], ft[1], -1L, kYP_GCIO, -108, vRealFld_GCIO, NULL, NULL);
          AddSubTypeField_GCIO(_hGXT, ft[0], ft[1], -1L, kGraphics_GCIO, -109, vUnknownItemType_GCIO, NULL, NULL);
          break;
        default          :
          AddSubTypeField_GCIO(_hGXT, ft[0], ft[1], -1L, kGraphics_GCIO, -109, vUnknownItemType_GCIO, NULL, NULL);
          break;
      }
      SetSubTypeGCHandle_GCIO(aSubclass,_hGXT);

      /* Add layer to data source layers list */
      poFile = new OGRGeoconceptLayer;
      if( poFile->Open(aSubclass) != OGRERR_NONE )
      {
        CSLDestroy(ft);
        delete poFile;
        return NULL;
      }

      _papoLayers = (OGRGeoconceptLayer **)
                      CPLRealloc( _papoLayers,  sizeof(OGRGeoconceptLayer *) * (_nLayers+1) );
      _papoLayers[_nLayers++] = poFile;

      CPLDebug("GEOCONCEPT",
               "nLayers=%d - last=[%s]",
               _nLayers, poFile->GetLayerDefn()->GetName());
    }
    CSLDestroy(ft);

/* -------------------------------------------------------------------- */
/*      Assign the coordinate system (if provided)                      */
/* -------------------------------------------------------------------- */
    if( poSRS != NULL )
        poFile->SetSpatialRef( poSRS );

    return poFile;
}
int OGRGeoconceptDataSource::LoadFile( const char *pszMode )

{
    OGRGeoconceptLayer *poFile;

    if( _pszExt == NULL)
    {
      const char* pszExtension = CPLGetExtension(_pszName);
      if( !EQUAL(pszExtension,"gxt") && !EQUAL(pszExtension,"txt") )
      {
        return FALSE;
      }
      _pszExt = CPLStrdup(pszExtension);
    }
    CPLStrlwr( _pszExt );

    if( !_pszDirectory )
        _pszDirectory = CPLStrdup( CPLGetPath(_pszName) );

    if( (_hGXT= Open_GCIO(_pszName,_pszExt,pszMode,_pszGCT))==NULL )
    {
      return FALSE;
    }

    /* Collect layers : */
    GCExportFileMetadata* Meta= GetGCMeta_GCIO(_hGXT);
    if( Meta )
    {
      int nC, iC, nS, iS;

      if( (nC= CountMetaTypes_GCIO(Meta))>0 )
      {
        GCType* aClass;
        GCSubType* aSubclass;

        for( iC= 0; iC<nC; iC++ )
        {
          if( (aClass= GetMetaType_GCIO(Meta,iC)) )
          {
            if( (nS= CountTypeSubtypes_GCIO(aClass)) )
            {
              for( iS= 0; iS<nS; iS++ )
              {
                if( (aSubclass= GetTypeSubtype_GCIO(aClass,iS)) )
                {
                  poFile = new OGRGeoconceptLayer;
                  if( poFile->Open(aSubclass) != OGRERR_NONE )
                  {
                    delete poFile;
                    return FALSE;
                  }

                  /* Add layer to data source layers list */
                  _papoLayers = (OGRGeoconceptLayer **)
                      CPLRealloc( _papoLayers,  sizeof(OGRGeoconceptLayer *) * (_nLayers+1) );
                  _papoLayers[_nLayers++] = poFile;

                  CPLDebug("GEOCONCEPT",
                           "nLayers=%d - last=[%s]",
                           _nLayers, poFile->GetLayerDefn()->GetName());
                }
              }
            }
          }
        }
      }
    }

    return TRUE;
}