#include <XSControl_FuncShape.ixx>
#include <Standard_ErrorHandler.hxx>
#include <Standard_Failure.hxx>

#include <XSControl.hxx>
#include <XSControl_Controller.hxx>
#include <XSControl_WorkSession.hxx>
#include <XSControl_Vars.hxx>
#include <IFSelect_Act.hxx>
#include <IFSelect_SessionPilot.hxx>
#include <IFSelect_Functions.hxx>

#include <Interface_InterfaceModel.hxx>
#include <Transfer_TransientProcess.hxx>
#include <Transfer_FinderProcess.hxx>
#include <Transfer_Finder.hxx>
#include <Transfer_Binder.hxx>
#include <Interface_CheckIterator.hxx>

//#include <TransferBRep_Analyzer.hxx>
#include <TransferBRep_ShapeMapper.hxx>
#include <TransferBRep_ShapeBinder.hxx>
#include <TransferBRep_ShapeListBinder.hxx>
#include <Transfer_SimpleBinderOfTransient.hxx>

#include <XSControl_ConnectedShapes.hxx>
#include <XSControl_TransferWriter.hxx>
#include <XSControl_TransferReader.hxx>
#include <TColStd_HSequenceOfTransient.hxx>
#include <Transfer_ResultFromModel.hxx>

#include <TopTools_HSequenceOfShape.hxx>
#include <TopoDS_Compound.hxx>
#include <BRep_Builder.hxx>
#include <TransferBRep.hxx>
#include <BRepTools.hxx>

#include <TopoDS.hxx>
#include <TColStd_SequenceOfInteger.hxx>
#include <TopExp_Explorer.hxx>

#include <Geom_Geometry.hxx>
#include <Geom2d_Curve.hxx>

#include <IFSelect_CheckCounter.hxx>
//skl#include <MoniTool_SignShape.hxx>
#include <ShapeExtend_Explorer.hxx>
//#include <MoniTool_DB.hxx>
#include <MDBLIST.hxx>
#include <Interface_Macros.hxx>
#include <stdio.h>
#include <TopoDS_Iterator.hxx>
#include <Transfer_TransientListBinder.hxx>


//  ######################################################################
//  ####                                                              ####
//  ####                           COMMANDS                           ####
//  ####                                                              ####
//  ######################################################################


//=======================================================================
//function : XSControl_tpdraw
//purpose  : 
//=======================================================================
static IFSelect_ReturnStatus XSControl_tpdraw
  (const Handle(IFSelect_SessionPilot)& pilot)
{
  Standard_Integer argc = pilot->NbWords();
  const Standard_CString arg1 = pilot->Arg(1);
  const Standard_CString arg2 = pilot->Arg(2);
  const Standard_CString arg3 = pilot->Arg(3);
  Handle(Transfer_TransientProcess) TP = XSControl::Session(pilot)->TransferReader()->TransientProcess();
  if (TP.IsNull()) { cout<<"No Transfer Read"<<endl; return IFSelect_RetError;}
  //        ****    tpdraw        ****
  if (argc < 2) {
    cout<<"Donner [mode facultatif : item ou root] , NUMERO , nom DRAW facultatif"<<endl;
    cout<<"  mode si present : item ou root, sinon n0 d entite modele"<<endl;
    cout<<"  NUMERO entier : d entite, d item transfert ou de root transfert\n"
      <<  "    ou * pour dire tous"<<endl;
    return IFSelect_RetError;
  }
  Standard_Integer mode = 0, num=0;
  if      (arg1[0] == 'i') mode = 1;
  else if (arg1[0] == 'r') mode = 2;
  Standard_Boolean tout = Standard_False;
  if (mode == 0) {
    if (argc < 2) { cout<<"Donner au moins un NUMERO ou *"<<endl; return IFSelect_RetError; }
    if (arg1[0] == '*') tout = Standard_True;
    else num = IFSelect_Functions::GiveEntityNumber(XSControl::Session(pilot),arg1);
  } else {
    if (arg2[0] == '*') tout = Standard_True;
    else num = IFSelect_Functions::GiveEntityNumber(XSControl::Session(pilot),arg2);
  }

  Standard_Integer nbvar = 0;
  Handle(Transfer_Binder) binder;
  Handle(Standard_Transient) ent;
  TopoDS_Shape sh;    char nomvar[40];
  //  Standard_Boolean moderoot =  (pilot->Word(0).Value(3) == 'r');

  Standard_Integer n1, n2, i, max=0, index=0;
  Handle(Interface_InterfaceModel) model = TP->Model();
  if (model.IsNull()) {
    if (mode == 0) {
      cout<<"Pas de modele, preciser n0 d item de transfert"<<endl;
      return IFSelect_RetError;
    }
  }
  if (mode == 0) { cout<<"Entite de modele";    max = model->NbEntities(); }
  if (mode == 1) { cout<<"Item de transfert";   max = TP->NbMapped(); }
  if (mode == 2) { cout<<"Racine de transfert"; max = TP->NbRoots(); }
  if (tout) {
    n1 = 1;  n2 = max;
    cout<<", listage de 1 a "<<max<<endl;
  }
  else if (num <= 0 || num > max) {
    cout<<" - Num="<<num<<" hors limite (de 1 a "<<max<<")"<<endl;
    return IFSelect_RetError;
  } else {
    n1 = n2 = num;  nbvar = -1;  // nbvar : 1ere shape simple = pas de n0
    cout<<", n0 "<<num<<endl;
  }

  for (i = n1; i <= n2; i ++) {
    if        (mode == 0) {
      ent = model->Value(i);
      num = i;
      index = TP->MapIndex(ent);
    } else if (mode == 1) {
      ent = TP->Mapped(i);
      if (model.IsNull()) num = 0;
      else num = model->Number(ent);
      index = i;
    } else if (mode == 2) {
      ent = TP->Root(i);
      if (model.IsNull()) num = 0;
      else num = model->Number(ent);
      index = TP->MapIndex(ent);
    }

    if (index > 0) binder = TP->MapItem (index);
    if (binder.IsNull()) index = 0;
    if (index == 0) {
      if (!tout) cout<<"Entite n0 "<<num<<" : non repertoriee"<<endl;
      continue;
    }
    if (!binder->HasResult()) {
      if (!tout) cout<<"Entite n0 "<<num<<" : pas de resultat"<<endl;
      continue;
    }
    sh = TransferBRep::ShapeResult (binder);
    //DeclareAndCast(TransferBRep_ShapeBinder,shb,binder);
    if (!sh.IsNull()) {
      //sh = shb->Result();
      nbvar ++;
      if (sh.IsNull()) { cout<<" (no Shape recorded)"<<endl; continue; }
      if (tout) cout<<"[ "<<i<<" ]:";
      if (num == 0) cout<<" pas dans le modele";
      else cout<<" ent.n0 "<<num;
      cout<<", item transfert n0 "<<index;
      if (nbvar == 0) {
	if      (argc > 3 && mode  > 0) sprintf (nomvar,"%s",arg3);
	else if (argc > 2 && mode == 0) sprintf (nomvar,"%s",arg2);
	else                            sprintf (nomvar,"tp_%d",i);
      } else {
	if      (argc > 3 && mode  > 0) sprintf (nomvar,"%s_%d",arg3,nbvar);
	else if (argc > 2 && mode == 0) sprintf (nomvar,"%s_%d",arg2,nbvar);
	else                            sprintf (nomvar,"tp_%d",i);
      }
      cout<<" -> 1 DRAW Shape: "<<nomvar<<endl;
      XSControl::Vars(pilot)->SetShape(nomvar,sh);
      continue;
    }
    DeclareAndCast(TransferBRep_ShapeListBinder,slb,binder);
    if (!slb.IsNull()) {
      Standard_Integer nbs = slb->NbShapes();
      if (tout) cout<<"[ "<<i<<" ]:";
      if (num == 0) cout<<" pas dans le modele";
      else cout<<" ent.n0 "<<num;
      cout<<", item transfert n0 "<<index;
      cout<<" -> "<<nbs<<" DRAW Shapes :";
      for (Standard_Integer j = 1; j <= nbs; j ++)  {
	sh = slb->Shape(j);  if (nbvar < 0) nbvar = 0;  nbvar ++;
	if (sh.IsNull()) { cout<<" (no Shape recorded)"<<endl; continue; }
	if      (argc > 3 && mode  > 0) sprintf (nomvar,"%s_%d",arg3,nbvar);
	else if (argc > 2 && mode == 0) sprintf (nomvar,"%s_%d",arg2,nbvar);
	else                        sprintf (nomvar,"tp_%d_%d",i,nbvar);
	cout<<" "<<nomvar;
	XSControl::Vars(pilot)->SetShape(nomvar,sh);
      }
      cout<<endl;
      continue;
    }
    DeclareAndCast(Transfer_SimpleBinderOfTransient,trb,binder);
    if (!trb.IsNull()) {
      Handle(Standard_Transient) resu = trb->Result();
      if (resu.IsNull()) {
	cout<<"Entite n0 "<<num<<" : pas de resultat"<<endl;
	continue;
      }
      DeclareAndCast(Geom_Geometry,geom,resu);
      cout<<"Entite n0 "<<num<<" : resultat "<<resu->DynamicType()->Name();
      if (geom.IsNull()) { cout<<endl; continue; }
      nbvar ++;
      if (nbvar == 0) {
	if      (argc > 3 && mode  > 0) sprintf (nomvar,"%s",arg3);
	else if (argc > 2 && mode == 0) sprintf (nomvar,"%s",arg2);
	else                            sprintf (nomvar,"tp_%d",i);
      } else {
	if      (argc > 3 && mode  > 0) sprintf (nomvar,"%s_%d",arg3,nbvar);
	else if (argc > 2 && mode == 0) sprintf (nomvar,"%s_%d",arg2,nbvar);
	else                            sprintf (nomvar,"tp_%d",i);
      }
      char* nomv = nomvar;
      XSControl::Vars(pilot)->Set (nomv,geom);
      cout<<" -> DRAW Geom : "<<nomvar<<endl;
      continue;
    }

    if (sh.IsNull() && trb.IsNull())
      if (!tout) cout<<"Entite n0 "<<num<<" : resultat pas une Shape mais "<<binder->ResultTypeName()<<endl;
  }

  if (sh.IsNull()) cout<<" (No Shape)"<<endl;
  return IFSelect_RetDone;
}

//=======================================================================
//function : XSControl_tpcompound
//purpose  : 
//=======================================================================
static IFSelect_ReturnStatus XSControl_tpcompound
  (const Handle(IFSelect_SessionPilot)& pilot)
{
  Standard_Integer argc = pilot->NbWords();
  const Standard_CString arg1 = pilot->Arg(1);
  Handle(Transfer_TransientProcess) TP = XSControl::Session(pilot)->TransferReader()->TransientProcess();
  if (TP.IsNull()) { cout<<"No Transfer Read"<<endl; return IFSelect_RetError;}
  //        ****    tpcompound        ****
  if (argc < 2) { cout<<"Give a NAME for the Compound  + optional givelist, else roots are taken"<<endl; return IFSelect_RetError; }
  Handle(TopTools_HSequenceOfShape) list;
  if (argc == 2) list = TransferBRep::Shapes(TP);
  else {
    Handle(TColStd_HSequenceOfTransient) lise = IFSelect_Functions::GiveList(pilot->Session(),pilot->CommandPart(2));
    if (lise.IsNull()) { cout<<"Not a valid entity list : "<<pilot->CommandPart(2)<<endl; return IFSelect_RetError; }
    list = TransferBRep::Shapes (TP,lise);
    cout<<lise->Length()<<" Entities, ";
  }
  if (list.IsNull()) { cout<<"No Shape listed"<<endl; return IFSelect_RetError; }
  Standard_Integer nb = list->Length();
  cout<<nb<<" Shape(s) listed"<<endl;
  TopoDS_Compound C;
  BRep_Builder B;
  B.MakeCompound(C);
  for (Standard_Integer i = 1; i <= nb; i ++)  B.Add (C,list->Value(i));
  XSControl::Vars(pilot)->SetShape (arg1,C);
  return IFSelect_RetDone;
}



//=======================================================================
//function : XSControl_traccess
//purpose  : 
//=======================================================================
static IFSelect_ReturnStatus XSControl_traccess
  (const Handle(IFSelect_SessionPilot)& pilot)
{
  Standard_Integer argc = pilot->NbWords();
  const Standard_CString arg1 = pilot->Arg(1);
  const Standard_CString arg2 = pilot->Arg(2);
  //        ****    trdraw : TransferReader        **** 26
  //        ****    trsave : TransferReader        **** 27
  //        ****    trcomp  (comp -> DRAW)         **** 28
  //        ****    trscomp (comp -> save)         **** 29
  Standard_Boolean cascomp = (pilot->Word(0).Location(1,'o',1,5) > 0);
  Standard_Boolean cassave = (pilot->Word(0).Location(1,'s',1,5) > 0);
  char nomsh[100], noms[100];
  Handle(XSControl_TransferReader)  TR  = XSControl::Session(pilot)->TransferReader();
  if (TR.IsNull()) { cout<<" manque init"<<endl; return IFSelect_RetError; }
  Handle(Interface_InterfaceModel)  mdl = TR->Model();
  if (mdl.IsNull()) { cout<<" modele absent"<<endl; return IFSelect_RetError; }
  Standard_Integer num = (argc > 1 ? IFSelect_Functions::GiveEntityNumber(XSControl::Session(pilot),arg1) : 0);

  if (argc > 1) strcpy (nomsh,arg1);
  else    strcpy (nomsh,(cascomp ? "TREAD_COMP" : "TREAD_LIST"));
  if (cassave) cout<<" save shapes -> current directory"<<endl;

  if (num == 0 || cascomp) {
    TopoDS_Compound C;        // pour cas compound
    BRep_Builder B;
    B.MakeCompound(C);

    Handle(TopTools_HSequenceOfShape) list = TR->ShapeResultList(Standard_True);
    Standard_Integer i,  nb = list->Length();
    cout<<" TOUS RESULTATS par ShapeResultList, soit "<<nb<<endl;
    for (i = 1; i <= nb; i ++) {
      sprintf (noms,"%s_%d",nomsh,i);
      if      ( (i%1000) == 0) cout<<"("<<i<<")"<<endl;
      else if ( (i%100)  == 0) cout<<"*"<<flush;
      else if ( (i%10)   == 0) cout<<"0"<<flush;
      else                     cout<<"."<<flush;
      if (list->Value(i).IsNull()) continue;
      if      (!cascomp && !cassave) XSControl::Vars(pilot)->SetShape(noms,list->Value(i));
      else if (!cascomp &&  cassave) BRepTools::Write (list->Value(i),noms);
      else if (cascomp) B.Add (C,list->Value(i));
    }
    cout<<endl;
    if      (cascomp && !cassave) XSControl::Vars(pilot)->SetShape(nomsh,C);
    else if (cascomp &&  cassave) BRepTools::Write (C,nomsh);
  } else {
    if (num < 1 || num > mdl->NbEntities()) { cout<<" incorrect:"<<arg1<<endl; return IFSelect_RetError; }
    TopoDS_Shape sh = TR->ShapeResult(mdl->Value(num));
    if (sh.IsNull()) { cout<<" Pas de resultat pour "<<arg1<<endl; return IFSelect_RetError; }
    if (argc > 2) sprintf (nomsh,"%s",arg2);
    else sprintf (nomsh,"TREAD_%d",num);
    if      (!cascomp && !cassave) XSControl::Vars(pilot)->SetShape(nomsh,sh);
    else if (!cascomp &&  cassave) BRepTools::Write (sh,nomsh);
    else cout<<"Option non comprise"<<endl;
  }
  return IFSelect_RetDone;
}

//=======================================================================
//function : XSControl_IsEqualSubShape
//purpose  : 
//=======================================================================
// PTV 23.08.2000 Added for checking where are an entity from.
static Standard_Boolean XSControl_IsEqualSubShape (const TopoDS_Shape& Shape,
                                                   TopoDS_Shape& sh, Standard_Integer aLevel)
{
  if ( sh.IsSame(Shape) ) return Standard_True;
  if (aLevel > 0) {
    TopoDS_Shape varShape;
    aLevel--;
    TopoDS_Iterator it(sh);
    for (; it.More(); it.Next() ) {
      varShape = it.Value();
      if ( XSControl_IsEqualSubShape(Shape, varShape, aLevel) ) return Standard_True;
    }
  }
  return Standard_False; 
}

//=======================================================================
//function : XSControl_fromshape
//purpose  : 
//=======================================================================
static IFSelect_ReturnStatus XSControl_fromshape
  (const Handle(IFSelect_SessionPilot)& pilot)
{
  Standard_Integer argc = pilot->NbWords();
  const Standard_CString arg1 = pilot->Arg(1);
  //        ****    fromshape (tread)         ****
  if (argc < 2) {
    cout<<"Give name of a DRAW Shape"<<endl;
    return IFSelect_RetError;
  }
  char* a1 = arg1;
  TopoDS_Shape Shape = XSControl::Vars(pilot)->GetShape(a1);
  if (Shape.IsNull()) {
    cout<<"Not a DRAW Shape:"<<arg1<<endl;
    return IFSelect_RetError;
  }
  Standard_Boolean yena = Standard_False;
  Standard_Integer aLevel = 1;
  if (argc >=3 )
    aLevel = atoi(pilot->Arg(2));
  Standard_Boolean silent = Standard_False;
  if (aLevel <0 ) {
    silent = Standard_True;
    aLevel = -aLevel;
  }
  
  //    IMPORT
  Handle(XSControl_TransferReader)  TR  = XSControl::Session(pilot)->TransferReader();
  if (TR.IsNull()) { }  // cout<<"No read transfer (import) recorded"<<endl;
  else {
    yena = Standard_True;
    if ( ! silent ) cout<<"Shape "<<arg1<<" : "<<flush;
    Standard_Integer modrec = 1;
    Handle(Standard_Transient) ent = TR->EntityFromShapeResult (Shape,modrec);
    if (ent.IsNull()) {
      modrec = -1;
      ent = TR->EntityFromShapeResult (Shape,modrec);
    }
    if (ent.IsNull()) {
      modrec = 2;
      Handle(Transfer_TransientProcess) TP = TR->TransientProcess();
      if (TP.IsNull()) {
        if ( silent )
          cout << "Shape "<<arg1<<" : ";
        cout<<"no map"<<endl;
      }
      else {
	TopoDS_Shape S0 = Shape;
	TopLoc_Location L;
	S0.Location ( L );
	Standard_Integer i, nb = TP->NbMapped();
	if ( ! silent ) cout<<"searching in map among "<<nb<<" ..."<<flush;
	for (i = 1; i <= nb; i ++) {
	  ent = TP->Mapped(i);
	  TopoDS_Shape sh = TransferBRep::ShapeResult(TP,ent);
	  if (sh.IsNull()) {
            ent.Nullify();
            continue;
          }
	  if (XSControl_IsEqualSubShape(Shape, sh, aLevel)) break;
	  modrec = -2;
	  sh.Location ( L );
	  if (XSControl_IsEqualSubShape(S0, sh, aLevel)) break;
	  ent.Nullify();
	  modrec = 2;
	}
      }
    }
    if ( ! ent.IsNull() ) {
      if ( silent ) cout << "Shape " << arg1 << ": ";
      if (modrec <0) cout<<"(moved from origin) "<<flush;
      //else cout<<"(origin) "<<flush;
    }
    //  on affiche
    if (ent.IsNull()) {
      if ( ! silent ) cout<<" unknown as imported";
      // skl 11.05.2004
      // if Shape is a compound try to make "fromshape" for its subshapes
      if(Shape.ShapeType()==TopAbs_COMPOUND) {
        cout<<endl<<"Subshapes imported from entities:";
        TopoDS_Iterator Iter(Shape);
        for (; Iter.More(); Iter.Next()) {
          TopoDS_Shape subsh = Iter.Value();
          Standard_Integer submodrec = 1;
          Handle(Standard_Transient) subent = TR->EntityFromShapeResult(subsh,submodrec);
          if (subent.IsNull()) {
            submodrec = -1;
            subent = TR->EntityFromShapeResult(subsh,submodrec);
          }
          if (!subent.IsNull()) {
            cout<<"  "<<XSControl::Session(pilot)->Model()->Number(subent); 
          }
        }
      }
    }
    else { 
      cout<<"imported from entity "; 
      XSControl::Session(pilot)->Model()->Print(ent,cout); 
      if ( silent ) cout << " in file " << XSControl::Session(pilot)->LoadedFile() << endl;
    }
    if ( ! silent ) cout<<endl;
  }

  //   ET EN EXPORT ?
  Handle(Transfer_FinderProcess) FP = XSControl::Session(pilot)->MapWriter();
  if (FP.IsNull()) { }  //cout<<"No write transfer (export) recorded"<<endl;
  else {
    yena = Standard_True;
    Handle(Transfer_Finder) fnd = TransferBRep::ShapeMapper (FP,Shape);
    Handle(Standard_Transient) ent;
    if (!fnd.IsNull()) ent = FP->FindTransient (fnd);
    if (!ent.IsNull()) {
      cout<<"Shape "<<arg1<<": exported to entity ";
      XSControl::Session(pilot)->Model()->Print(ent,cout);
      if ( silent ) cout << " in file " << XSControl::Session(pilot)->LoadedFile();
      cout<<endl;
    }
    // abv 31.08.00: treat case of splitted shape (several results)
    // it is supposed that results are of the same type and lie in one-level comp
    else {
      Handle(Transfer_Binder) bnd = FP->Find ( fnd );
      if ( ! bnd.IsNull() ) {
	Handle(Transfer_TransientListBinder) TransientListBinder =
	  //Handle(Transfer_TransientListBinder)::DownCast( bnd->Next(Standard_True) ); //skl
	  Handle(Transfer_TransientListBinder)::DownCast( bnd ); //skl
	if (! TransientListBinder.IsNull() ) {
	  Standard_Integer i = 1, nb = TransientListBinder->NbTransients();
	  if (nb > 0) cout<<"Shape "<<arg1<<": exported to entities ";
	  for (; i<=nb; i++) {
	    XSControl::Session(pilot)->Model()->Print( TransientListBinder->Transient(i), cout );
	    if (i < nb) cout<<", ";
	  }
	  if (nb > 0) {
	    if ( silent ) cout << " in file " << XSControl::Session(pilot)->LoadedFile();
	    cout<<endl;
	  }
	}
/*	else {
	  TopoDS_Shape comp = TransferBRep::ShapeResult(bnd);
	  if ( ! comp.IsNull() && comp.ShapeType() < Shape.ShapeType() ) {
	    Standard_Boolean start = Standard_True;
	    for ( TopoDS_Iterator it(comp); it.More(); it.Next() ) {
	      Handle(Transfer_Finder) cfnd = TransferBRep::ShapeMapper (FP,it.Value());
	      if ( cfnd.IsNull() ) continue;
	      Handle(Standard_Transient) cent = FP->FindTransient (cfnd);
	      if ( cent.IsNull() ) continue;
	      if ( start ) 
		cout<<"Shape "<<arg1<<" : exported to entities ";
	      else cout << ", ";
	      start = Standard_False;
	      XSControl::Session(pilot)->Model()->Print(cent,cout);
	    }
	    if ( ! start ) cout<<endl;
	  }
	}  */
      }
    }
  }
  if (!yena) cout<<"No transfer (either import or export) recorded"<<endl;

  return IFSelect_RetVoid;
}

//=======================================================================
//function : XSControl_trconnexentities
//purpose  : 
//=======================================================================
static IFSelect_ReturnStatus XSControl_trconnexentities
  (const Handle(IFSelect_SessionPilot)& pilot)
{
  Standard_Integer argc = pilot->NbWords();
  const Standard_CString arg1 = pilot->Arg(1);
  //        ****    connected entities (last transfer)         ****
  Handle(XSControl_TransferReader)  TR  = XSControl::Session(pilot)->TransferReader();
  Handle(Transfer_TransientProcess) TP;
  if (!TR.IsNull()) TP = TR->TransientProcess();
  if (TP.IsNull()) { cout<<"no transfer map"<<endl; return IFSelect_RetVoid; }
  if (argc < 2) { cout<<"Give name of a DRAW Shape + optional shape type v-e-w-f(D)-s"<<endl; return IFSelect_RetError; }
  char* a1 = arg1;
  TopoDS_Shape Shape = XSControl::Vars(pilot)->GetShape(a1);
  if (Shape.IsNull()) { cout<<"Not a DRAW Shape:"<<arg1<<endl; return IFSelect_RetError; }
  cout<<"Shape "<<arg1<<" : "<<flush;

  Handle(TColStd_HSequenceOfTransient) list =
    XSControl_ConnectedShapes::AdjacentEntities (Shape,TP,TopAbs_FACE);
  Standard_Integer i, nb = list->Length();
  cout<<nb<<" Entities produced Connected Shapes :"<<endl;
  Handle(Interface_InterfaceModel) model = XSControl::Session(pilot)->Model();
  cout<<"(";
  for (i = 1; i <= nb; i ++) {
    if (i > 1) cout<<",";
    cout<<model->Number(list->Value(i));
  }
  cout<<")"<<endl;
  return IFSelect_RetDone;
}
  
//=======================================================================
//function : XSControl_trimport
//purpose  : 
//=======================================================================
static IFSelect_ReturnStatus XSControl_trimport
  (const Handle(IFSelect_SessionPilot)& pilot)
{
  //  FileName ou . (pour courant)  VarName  GiveList (obligatoire)
  //    GiveList : * pour xst-transferrable-roots
  Handle(XSControl_WorkSession) WS = XSControl::Session(pilot);

  Standard_Integer argc = pilot->NbWords();
  if (argc < 4) {
    cout<<"Give : filename or . for current model;  varname or . to take fileroot\n  GiveList, * for all transferrable roots"<<endl;
    return IFSelect_RetError;
  }
  const Standard_CString arg1 = pilot->Arg(1);
  const Standard_CString arg2 = pilot->Arg(2);
  const Standard_CString arg3 = pilot->Arg(3);

  //  File Name and Variable (root) Name

  TCollection_AsciiString fnom,rnom;
  Standard_Boolean modfic = XSControl_FuncShape::FileAndVar
    (WS,arg1,arg2,"IMPORT",fnom,rnom);
  if (modfic) cout<<" File to read : "<<fnom<<endl;
  else        cout<<" Model taken from the session : "<<fnom<<endl;
  cout<<" -- Names of variables BREP-DRAW prefixed by : "<<rnom<<endl;
  SDBCUR.Clear();

  //  keep the current command, because sub-commands will be called
  TCollection_AsciiString compart = pilot->CommandPart (3);

  //  Reading file if required

  if (modfic) {
    TCollection_AsciiString comload ("xload ");
    comload.AssignCat(arg1);
    IFSelect_ReturnStatus status = pilot->Execute(comload);
    if (status != IFSelect_RetDone)
      { cout<<"Abandon import"<<endl; return status; }
  } else {
    cout<<"Currently Loaded Model"<<endl;
  }

  //  Selecting Entities

  Handle(TColStd_HSequenceOfTransient)  list;
  if (arg3[0] == '*' && arg3[1] == '\0') {
    list = WS->GiveList ("xst-transferrable-roots");
    cout<<"All Transferrable Roots : ";
  } else {
    cout<<"List given by "<<compart.ToCString()<<" : ";
    list = WS->GiveList (compart.ToCString());
  }
  if (list.IsNull()) { cout<<"No list defined. Abandon"<<endl; return IFSelect_RetError; }
  Standard_Integer nbl = list->Length();
  cout<<"Nb entities selected : "<<nbl<<endl;

  //  Starting Transfer

  WS->InitTransferReader (0);
  Handle(XSControl_TransferReader) TR = WS->TransferReader();
  if (TR.IsNull()) { cout<<" init not done or failed"<<endl; return IFSelect_RetError; }

  TR->BeginTransfer();

  //  Transferring
  Standard_Integer nbt = TR->TransferList(list);
  cout<<"Nb Entities Selected : "<<nbl<<" have given "<<nbt<<" results"<<endl;

  //  Filling VARS. one compound (trimpcomp) or one shape per ent (trimport)
  Standard_Boolean iscomp = (pilot->Arg(0)[5] == 'c');
  Standard_Integer nbs = 0;
  TopoDS_Shape sh;
  TopoDS_Compound C;
  BRep_Builder B;
  B.MakeCompound (C);
  Handle(Interface_InterfaceModel)  mdl = TR->Model();
  if (mdl.IsNull()) { cout<<" modele absent"<<endl; return IFSelect_RetError; }
  for (Standard_Integer il= 1; il <= nbl; il ++) {
    Handle(Standard_Transient) ent = list->Value(il);
    sh = TR->ShapeResult(ent);
    if (sh.IsNull()) continue;
    nbs ++;
    if (iscomp) B.Add (C,sh);
    else {
      char nomsh[50];
      sprintf (nomsh,"%s_%d",rnom.ToCString(),nbs);
      XSControl::Vars(pilot)->SetShape(nomsh,sh);
    }
  }
  if (nbs == 0) cout<<"No Shape produced"<<endl;
  else if (nbs == 1) {
    cout<<"One Shape produced, named "<<rnom.ToCString()<<endl;
    XSControl::Vars(pilot)->SetShape(rnom.ToCString(),sh);
  } else if (iscomp) {
    cout<<"One compound made of "<<nbs<<" Shapes, named "<<rnom.ToCString()<<endl;
    XSControl::Vars(pilot)->SetShape(rnom.ToCString(),C);
  } else {  // several individual shapes
    cout<<nbs<<" Shapes, named "<<rnom.ToCString()<<"_1 to "<<rnom.ToCString()<<"_"<<nbs<<endl;
  }

  return IFSelect_RetDone;
}

//=======================================================================
//function : XSControl_twrite
//purpose  : 
//=======================================================================
static IFSelect_ReturnStatus XSControl_twrite
  (const Handle(IFSelect_SessionPilot)& pilot)
{
  Standard_Integer argc = pilot->NbWords();
  const Standard_CString arg1 = pilot->Arg(1);
  //        ****    twrite         ****
  Handle(XSControl_TransferWriter) TW = XSControl::Session(pilot)->TransferWriter();
  if (argc < 2) { cout<<" donner nom de shape draw"<<endl; return IFSelect_RetError; }
  cout<<"Attention, on alimente le modele courant ..."<<endl;

  // Shape
  for (Standard_Integer i = 1; i < argc; i ++) {
    char* ai = pilot->Arg(i);
    TopoDS_Shape Shape = XSControl::Vars(pilot)->GetShape(ai);
    if (Shape.IsNull()) { cout<<"pas un nom de shape draw:"<<arg1<<endl; continue; }
    cout<<"Pour Shape : "<<ai;
    Standard_Integer stat = TW->TransferWriteShape (XSControl::Session(pilot)->Model(),Shape);
    cout<<" Transfer Write Status = "<<stat<<endl;
  }
  pilot->Session()->ComputeGraph();
  // Transient ? (Geom) : ignore
  return IFSelect_RetDone;
}

//POP not used function 
/*
static IFSelect_ReturnStatus XSControl_twdraw
  (const Handle(IFSelect_SessionPilot)& pilot)
{
  Standard_Integer argc = pilot->NbWords();
  if (argc < 2) { cout<<"Designate an entity, + possible name for shape, else twitem_nnn"<<endl; return IFSelect_RetError; }
  const Standard_CString arg1 = pilot->Arg(1);
//        ****    twdraw         ****
  Handle(Transfer_FinderProcess) FP = XSControl::Session(pilot)->MapWriter();
  if (FP.IsNull()) { cout<<"No write transfer (export) recorded"<<endl; return IFSelect_RetError; }
  Standard_Integer  num = pilot->Number(arg1);
  if (num <= 0) { cout<<arg1<<" is not suitable for an entity"<<endl; return IFSelect_RetError; }

  Handle(Standard_Transient) ent = XSControl::Session(pilot)->StartingEntity(num);
  Standard_Integer i, nb = FP->NbMapped();
  Handle(Standard_Transient) res;
  Handle(Transfer_Finder) fnd;
  for (i = 1; i <= nb; i ++) {
    fnd = FP->Mapped(i);
    res = FP->FindTransient (fnd);
    if (res == ent) break;
    res.Nullify();
  }
  TopoDS_Shape Shape;
  if (res.IsNull()) cout<<"Unknown origin on export for "<<arg1<<endl;
  else {
    Handle(TransferBRep_ShapeMapper) Shelem =
      Handle(TransferBRep_ShapeMapper)::DownCast(fnd);
    if (!Shelem.IsNull()) Shape = Shelem->Value();
    if (Shape.IsNull()) cout<<"origin on export for "<<arg1<<" is not a Shape but a "<<fnd->ValueTypeName()<<endl;
  }
  if (Shape.IsNull()) return IFSelect_RetVoid;

  char nomvar[30];
  if (argc > 2) sprintf (nomvar,"tw_%d",num);
  else sprintf (nomvar,"%s",pilot->Arg(2));
  XSControl::Vars(pilot)->SetShape(nomvar,Shape);
  cout<<"Origin on export for entity "<<arg1<<" -> Shape "<<nomvar<<endl;
  return IFSelect_RetDone;
}
*/


// #################################
// ####        CHECKBREP        ####
// #################################

//=======================================================================
//function : checkbrep_sublist
//purpose  : 
//=======================================================================
/*
static void checkbrep_sublist
  (const Handle(XSControl_Vars)& vars,
   const Handle(TopTools_HSequenceOfShape)& sl, const char* arg2,
   const Standard_Integer num,const char opt, const Standard_CString name)
{
  Standard_Integer nb = sl->Length();
  if (nb > 0) {
    ShapeExtend_Explorer STU;
    TopoDS_Shape exp = STU.CompoundFromSeq (sl);
    char nomsh[80];
    if (num == 0) sprintf (nomsh,"%s_%c",arg2,opt);
    else          sprintf (nomsh,"%s_%d_%c",arg2,num,opt);
    cout<<name<<"	: "<<(nb > 9 ? "" : " ")<<nb<<" Items -> compound named "<<nomsh<<endl;
    vars->SetShape (nomsh,exp);
  }
}
*/


//=======================================================================
//function : checkbrep_ents
//purpose  : 
//=======================================================================
/*
static Standard_Integer checkbrep_ents
  (const Handle(IFSelect_SessionPilot)& pilot,
   const Handle(TopTools_HSequenceOfShape)& sl, const Standard_CString name)
{
  Handle(XSControl_TransferReader)  TR  = XSControl::Session(pilot)->TransferReader();
  //Handle(TColStd_HSequenceOfTransient) lise = TR->EntitiesFromShapeList (sl,1);
  //skl 05.12.2002 (searching as in command "fromshape")
  Handle(TColStd_HSequenceOfTransient) lise = new TColStd_HSequenceOfTransient;
  if (TR.IsNull()) return 0;
  for (Standard_Integer is=1; is<=sl->Length(); is++) {
    TopoDS_Shape Shape = sl->Value(is);
    Standard_Integer modrec = 1;
    Handle(Standard_Transient) ent = TR->EntityFromShapeResult (Shape,modrec);
    if (ent.IsNull()) {
      modrec = -1;
      ent = TR->EntityFromShapeResult (Shape,modrec);
    }
    if (ent.IsNull()) {
      modrec = 2;
      Handle(Transfer_TransientProcess) TP = TR->TransientProcess();
      if (!TP.IsNull()) {
        TopoDS_Shape S0 = Shape;
        TopLoc_Location L;
        S0.Location ( L );
        Standard_Integer i, nb = TP->NbMapped();
        for (i = 1; i <= nb; i ++) {
          ent = TP->Mapped(i);
          TopoDS_Shape sh = TransferBRep::ShapeResult(TP,ent);
          if (sh.IsNull())  {  ent.Nullify();  continue;  }
          if (XSControl_IsEqualSubShape(Shape,sh,1)) break;
          modrec = -2;
          sh.Location ( L );
          if (XSControl_IsEqualSubShape(S0,sh,1)) break;
          ent.Nullify();
          modrec = 2;
        }
      }
    }
    if ( !ent.IsNull() ) {
      lise->Append(ent);
    }
  }

  //Handle(TColStd_HSequenceOfTransient) lise =
  //  XSControl::Session(pilot)->TransferReader()->EntitiesFromShapeList (sl,1);
  Standard_Integer i, nb = lise->Length();
  if (nb > 0) cout<<name<<"	: "<<nb<<" , i.e. : "<<endl;
  for (i = 1; i <= nb; i ++) {
    cout<<"  "<<pilot->Session()->StartingNumber(lise->Value(i));
  }
  if (nb > 0) cout<<endl;
  return nb;
}
*/


//=======================================================================
//function : XSHAPE_checkbrep
//purpose  : 
//=======================================================================
/*
static IFSelect_ReturnStatus XSHAPE_checkbrep
  (const Handle(IFSelect_SessionPilot)& pilot)
{
  Standard_Integer argc = pilot->NbWords();
  const Standard_CString arg1 = pilot->Arg(1);
  const Standard_CString arg2 = pilot->Arg(2);
  const Standard_CString arg3 = pilot->Arg(3);
  Handle(XSControl_Vars) vars = XSControl::Vars(pilot);
  //        ****    BRepCheck         ****
  if (argc < 3) { cout<<"give shape name or * for all results + names for expurged shape & faulties"<<endl; return IFSelect_RetError; }
  char* a1 = arg1;
  //  On prend : une shape isolee si nom explicite
  //  tout resultat shape (tpcomp) si "*"
  Handle(TopTools_HSequenceOfShape) list;
  if (XSControl_FuncShape::MoreShapes (XSControl::Session(pilot),list,arg1)
      == 0) return IFSelect_RetVoid;
  TopAbs_ShapeEnum filtre = TopAbs_SHAPE;
  if (argc > 3) {
    if (arg3[0] == 'f') filtre = TopAbs_FACE;
    if (arg3[0] == 's') filtre = TopAbs_SHELL;
  }
  int one = 1;
  Standard_Integer i, nb = list->Length();
  if (a1[0] == '*' && a1[1] == '\0') {
    cout<<"-> Results from last transfer : "<<nb<<" Shapes"<<endl;
    one = 0;
  } else if (nb > 1) {
    cout<<"-> "<<nb<<" Shapes taken by "<<arg1<<endl;
    one = 0;
  }
  //  On analyse distinctement chaque shape
  //  Handle(Dico_DictionaryOfInteger) dic = new Dico_DictionaryOfInteger;
  Handle(TopTools_HSequenceOfShape) sl, slv,sle,slw,slf,sls,slo;
  TColStd_SequenceOfInteger numsh;
  Standard_Integer nbmax = 0;
  for (i = 1; i <= nb; i ++) {
    if (list->Value(i).IsNull()) continue;
    TransferBRep_Analyzer ana;
    Standard_Integer nbfilt = 0;
    ana.Check (list->Value(i),2);
    Interface_CheckIterator chl = ana.CheckResult();
    if (chl.IsEmpty(Standard_False)) {
      if (one) cout<<" -- The Shape "<<arg1<<" looks OK"<<endl;
      else     cout<<"#"<<flush;
      continue;
    }
    if (one) cout<<" -- The Shape "<<arg1<<" has problems : ";
    else     cout<<" -- The Shape n0 "<<i<<" has problems : ";
    //abv 12.07.00: commented to avoid long unuseful listings in checkbrep:
    //    chl.Print (cout,Standard_False);
    if (!chl.IsEmpty(Standard_False)) {
      cout<<endl<<"  I.E. per Shape Type + Message"<<endl;
      Handle(IFSelect_CheckCounter) chc = new IFSelect_CheckCounter;
//skl      chc->SetSignature (new MoniTool_SignShape);
      chc->Analyse (chl,chl.Model());
      chc->PrintList (cout,chl.Model(),IFSelect_CountByItem);
    }
    numsh.Append(i);
    //    les faulties
    sl = ana.CheckedShapes();
    slv = new TopTools_HSequenceOfShape();
    sle = new TopTools_HSequenceOfShape();
    slw = new TopTools_HSequenceOfShape();
    slf = new TopTools_HSequenceOfShape();
    sls = new TopTools_HSequenceOfShape();
    slo = new TopTools_HSequenceOfShape();
    Standard_Integer ii, nbs = sl->Length();
    if (nbs > nbmax) nbmax = nbs;
    cout<<"*** Shapes with problems:"<<nbs;
    if (argc == 2)  {  cout<<endl;  continue;  }
    if (one) cout<<" for "<<arg1<<" : from "<<arg2<<"_1 to "<<arg2<<"_"<<nbs<<endl;
    else cout<<" for result n0 "<<i<<" : from "<<arg2<<"_"<<i<<"_1 to "<<arg2<<i<<"_"<<nbs<<endl;
    for (ii = 1; ii <= nbs; ii ++) {
      TopoDS_Shape shi = sl->Value(ii);
      TopAbs_ShapeEnum sti = shi.ShapeType();
      switch (sti) {
        case TopAbs_VERTEX : slv->Append (shi); break;
        case TopAbs_EDGE   : sle->Append (shi); break;
        case TopAbs_WIRE   : slw->Append (shi); break;
        case TopAbs_FACE   : slf->Append (shi); break;
        case TopAbs_SHELL  : sls->Append (shi); break;
        case TopAbs_SOLID  : slo->Append (shi); break;
        default            : break;
      }
      cout<<"."<<flush;
      char nomsh[80];
      if (one) sprintf(nomsh,"%s_%d",arg2,ii);
      else     sprintf(nomsh,"%s_%d_%d",arg2,i,ii);
      XSControl::Vars(pilot)->SetShape(nomsh,shi);
    }
    cout<<endl;
    //     les paquets par type de shapes faulty
    checkbrep_sublist (vars,slv,arg2,(one ? 0 : i),'v',"VERTEX");
    checkbrep_sublist (vars,sle,arg2,(one ? 0 : i),'e',"EDGE");
    checkbrep_sublist (vars,slw,arg2,(one ? 0 : i),'w',"WIRE");
    checkbrep_sublist (vars,slf,arg2,(one ? 0 : i),'f',"FACE");
    checkbrep_sublist (vars,sls,arg2,(one ? 0 : i),'s',"SHELL");
    checkbrep_sublist (vars,slo,arg2,(one ? 0 : i),'o',"SOLID");
    //     la shape expurgee
    if (nbs > 0) {
      char nomsh[80];
      cout<<endl<<"Expurged Shape ";  if (!one) cout<<" n0 "<<i;
      if (one) sprintf(nomsh,"%s",arg2);
      else     sprintf(nomsh,"%s_%d",arg2,i);
      cout<<" -> DRAW "<<nomsh<<endl;
      TopoDS_Shape expu = ana.Expurge (list->Value(i),2);
      if (expu.IsNull()) cout<<"Shape expurgee vide ..."<<endl;
      else XSControl::Vars(pilot)->SetShape(nomsh,expu);
    } else {
      char nomsh[80];
      cout<<endl<<"Expurged Shape = Starting Shape";  if (!one) cout<<" for n0 "<<i;
      if (one) sprintf(nomsh,"%s",arg2);
      else     sprintf(nomsh,"%s_%d",arg2,i);
      cout<<" -> DRAW "<<nomsh<<endl;
      XSControl::Vars(pilot)->SetShape(nomsh,list->Value(i));
    }

    //     shapes a pb (directement ou non) selon mode
    if (filtre != TopAbs_SHAPE) {
      TopoDS_Compound compfilt;
      BRep_Builder BCF;
      BCF.MakeCompound (compfilt);
      char nomsh[80];  nbfilt = 0;
      for (TopExp_Explorer filtex (list->Value(i),filtre);
	   filtex.More();  filtex.Next()) {
	TopoDS_Shape afiltrer = filtex.Current();
	if (ana.ContainsChecked (afiltrer)) {
	  nbfilt ++;
	  if (one) sprintf (nomsh,"%s%s_%d",arg2,arg3,nbfilt);
	  else     sprintf (nomsh,"%s%s_%d_%d",arg2,arg3,i,nbfilt);
	  XSControl::Vars(pilot)->SetShape (nomsh,afiltrer);
	  BCF.Add (compfilt,afiltrer);
	}
      }
      if (nbfilt > 0) {
	if (one) cout<<"Shapes filtered from "<<arg2<<arg3<<"_1 to "<<arg2<<arg3<<"_"<<nbfilt;
	else     cout<<"Shapes filtered from "<<arg2<<arg3<<"_"<<i<<"_1 to "<<arg2<<arg3<<"_"<<i<<"_"<<nbfilt;
	sprintf (nomsh,"%s%s",arg2,arg3);
	cout<<" + in compound : "<<nomsh<<endl;
	XSControl::Vars(pilot)->SetShape (nomsh,compfilt);
      }
    }
  }
  if (nbmax > 0) cout<<"Nb maxi of shapes with problems per tested shape : "<<nbmax<<endl;

  nb = numsh.Length();
  if (!one && nb > 0) {
    cout<<" -- Input Shapes with problems : "<<nb<<" i.e. n0s ";
    for (i = 1; i <= nb; i ++) cout<<" "<<numsh.Value(i);
    cout<<endl;
  }

  if (nb > 0) {
    cout<<" -- Starting (from file) Entities when known, per Shape Type"<<endl;
    Standard_Integer nbs = 0;
    nbs += checkbrep_ents (pilot,slv,"VERTEX");
    nbs += checkbrep_ents (pilot,sle,"EDGE");
    nbs += checkbrep_ents (pilot,slw,"WIRE");
    nbs += checkbrep_ents (pilot,slf,"FACE");
    nbs += checkbrep_ents (pilot,sls,"SHELL");
    nbs += checkbrep_ents (pilot,slo,"SOLID");
    cout<<"Total Listed (All Types) : "<<nbs<<endl;
  }
  else if (!one) cout<<" -- All seams to be OK ..."<<endl;
  return IFSelect_RetDone;
}
*/

// #################################
// ####          DBLIST         ####
// #################################

/*skl
static IFSelect_ReturnStatus XSHAPE_dblist
  (const Handle(IFSelect_SessionPilot)& pilot)
{
  if (pilot->NbWords() < 2) {
    cout<<"Give an option :\n  clear   nb   index   set nn   data n1 n2"<<endl;
    return IFSelect_RetError;
  }
  Standard_CString opt = pilot->Arg(1);
  char opt1 = opt[0];
  MoniTool_DB& dbl = MoniTool_DB::Cur();
  switch (opt1) {
  case 'c' : dbl.Clear();  break;
  case 'd' : {
    char nomdb[50];
    if (pilot->NbWords() < 4) { cout<<"Give n0 set and n0/name of data in set"<<endl;  return IFSelect_RetError; }
    Standard_Integer n1 = atoi (pilot->Arg(2));
    Standard_Integer n2 = atoi (pilot->Arg(3));
    if (n2 == 0) n2 = dbl.DataNum (n1,pilot->Arg(3));
    if (n2 == 0) { cout<<pilot->Arg(3)<<" is not a suitable name for set "<<n1<<endl;  return IFSelect_RetError; }
    Standard_Integer kind = dbl.Kind (n1,n2);
    cout<<" Set "<<n1<<" , Data "<<n2<<" -> DRAW dbl_"<<n1<<"_"<<n2;
    sprintf (nomdb,"dbl_%d_%d",n1,n2);
    if (kind == 4) {
      cout<<"  (Shape)"<<endl;
      TopoDS_Shape sh = dbl.Shape (n1,n2);
      if (!sh.IsNull()) XSControl::Vars(pilot)->SetShape (nomdb,sh);
      else cout<<"  Pas une shape"<<endl;
    }
    else if (kind == 3) {
      cout<<"  (Geometry)"<<endl;
      char* nomdr = nomdb;
      DeclareAndCast(Geom_Geometry,geom,dbl.Data(n1,n2));
      DeclareAndCast(Geom2d_Curve,geom2d,dbl.Data(n1,n2));
      if (!geom.IsNull()) XSControl::Vars(pilot)->Set (nomdr,geom);
      else if (!geom2d.IsNull()) XSControl::Vars(pilot)->Set (nomdr,geom2d);
      else cout<<"  Not a geometry"<<endl;
    }
    else cout<<"  Neither Shape nor Geometry"<<endl;
    //dbl.Print (cout,n1,n2);
    break;
  }
  case 'i' : dbl.Print (cout,1,0);  break;
  case 'n' : dbl.Print (cout,0,0);  break;
  case 's' : {
    if (pilot->NbWords() < 3) { cout<<"Give n0 set"<<endl;  return IFSelect_RetError; }
    Standard_Integer n1 = atoi (pilot->Arg(2));
    dbl.Print (cout,XSControl::Session(pilot)->Model(),0,n1);
    break;
  }
    default : cout<<"Option unknown : "<<opt<<endl;
  }
  return IFSelect_RetVoid;
}
skl*/

//  ######################################################################
//  ####                    TIMERS                                    ####
//  ######################################################################


//  ######################################################################
//  ####                                                              ####
//  ####                    Initialising Commands                     ####
//  ####                                                              ####
//  ######################################################################

static int initactor = 0;


//=======================================================================
//function : Init
//purpose  : 
//=======================================================================

void  XSControl_FuncShape::Init ()
{
  if (initactor) return;  initactor = 1;

  IFSelect_Act::SetGroup("DE: General");

  IFSelect_Act::AddFunc ("tpdraw","[mode:item or root]  num|*  [nomvar] Passes an ITEM to Shape Draw (Start or Result)",XSControl_tpdraw);

  IFSelect_Act::AddFunc ("tpcompound","name:cstring [givelist] : -> compound with Shapes Root or from givelist",XSControl_tpcompound);

  IFSelect_Act::AddFunc ("trdraw","results ->DRAW : all;  or num [name] : from ent.num -> DRAW [name/tread_num]",XSControl_traccess);
  IFSelect_Act::AddFunc ("trsave","results ->files : all;  or num [name] : from ent.num -> DRAW [name/tread_num]",XSControl_traccess);
  IFSelect_Act::AddFunc ("trcomp","results -> 1 compound -> DRAW + name optional",XSControl_traccess);
  IFSelect_Act::AddFunc ("trscomp","results -> 1 compound -> file + name optional",XSControl_traccess);

  IFSelect_Act::AddFunc ("fromshape","shape [level=1]: imported/exported entity (when known)",XSControl_fromshape);
  IFSelect_Act::AddFunc ("trconnexent","name of draw shape : entities -> connected shapes (when known)",XSControl_trconnexentities);

  IFSelect_Act::AddFunc ("trimport","filename or .  varname  givelist  -> 1 shape per entity",XSControl_trimport);
  IFSelect_Act::AddFunc ("trimpcomp","filename or .  varname  givelist -> one xcompound",XSControl_trimport);

  IFSelect_Act::AddFunc ("twrite","shape : transfer write for this shape, AFTER newmodel !",XSControl_twrite);

  //skl IFSelect_Act::AddFunc ("checkbrep","shapename or * [+ rootname for expurged and faulties [+ mode f-s]]",XSHAPE_checkbrep);
  //skl IFSelect_Act::AddFunc ("dblist","option : clear  nb  index  set n1  data n1 n2",XSHAPE_dblist);
}

//  ######################################################################
//  ####                                                              ####
//  ####                      Additional Methods                      ####
//  ####                                                              ####
//  ######################################################################


//=======================================================================
//function : MoreShapes
//purpose  : 
//=======================================================================

Standard_Integer  XSControl_FuncShape::MoreShapes
  (const Handle(XSControl_WorkSession)& session,
   Handle(TopTools_HSequenceOfShape)& list, const Standard_CString name)
{
  //  name = un nom -> Draw
  //  name = "*"    -> tous les transferts RACINES du TP
  //  name = "**"   -> tous les transferts du TP : VRAIMENT TOUS
  //  name = "."    -> reperage graphique (not yet impl)
  //  name = nom(n1-n2) avec n1,n2 entiers :  les variables de nom  nomn1 a nomn2
  if (list.IsNull()) list = new TopTools_HSequenceOfShape();
  if (name[0] == '*' && (name[1] == '\0' || (name[1] == '*' && name[2] == '\0'))) {
    Handle(Transfer_TransientProcess)  TP  = session->TransferReader()->TransientProcess();
    if (TP.IsNull()) { cout<<"last transfer : unknown"<<endl;return 0; }
    Handle(TopTools_HSequenceOfShape) li = TransferBRep::Shapes(TP,(name[1] == '\0'));
    if (li.IsNull()) return 0;
    list->Append (li);
    return li->Length();
  }
  Standard_Integer i, paro = 0, parf = 0, moins = 0, n1 = 0, n2 = 0;
  for (i = 0; name[i] != '\0'; i ++) {
    if (name[i] == '(') paro  = i;
    if (name[i] == '-') moins = i;
    if (name[i] == ')') parf  = i;
  }
  if (paro && moins && parf) {
    n2 = atoi (&name[moins+1]);
    n1 = atoi (&name[paro +1]);  if (n1 < 0) n1 += n2; // sinon on a n1-n2
  }
  //  liste
  if (n1 <= n2 && n1 > 0) {
    char nom[50], nomsh[60];  Standard_Integer nbsh = 0;
    for (i = 0; i < paro; i ++) nom[i]=name[i];   nom[paro] = '\0';
    cout<<"Shapes DRAW named : "<<nom<<n1<<" to "<<nom<<n2;
    for (i = n1; i <= n2 ; i ++) {
      char* nomshh = &nomsh[0];
      sprintf (nomsh,"%s%d",nom,i);
      TopoDS_Shape Shape = session->Vars()->GetShape(nomshh);
      if (Shape.IsNull()) continue;
      list->Append(Shape);
      nbsh ++;
    }
    cout<<"  -> taken "<<nbsh<<" Shapes"<<endl;
    return nbsh;
  }
  char* a1 = name;
  TopoDS_Shape Shape = session->Vars()->GetShape(a1);
  if (Shape.IsNull()) { cout<<"not a shape draw:"<<a1<<endl; return 0; }
  list->Append(Shape);
  return 1;
}


//=======================================================================
//function : FileAndVar
//purpose  : 
//=======================================================================

Standard_Boolean  XSControl_FuncShape::FileAndVar
  (const Handle(XSControl_WorkSession)& session,
   const Standard_CString file, const Standard_CString var,
   const Standard_CString def,
   TCollection_AsciiString& resfile,   TCollection_AsciiString& resvar)
{
  Standard_Boolean iafic = Standard_True;
  resfile.Clear();  resvar.Clear();
  if (file)
    if ( file[0] == '\0' ||
        (file[0] == '.' && file[1] == '\0')) iafic = Standard_False;
  if (!iafic) resfile.AssignCat (session->LoadedFile());
  else        resfile.AssignCat (file);
 
  if (var && var[0] != '\0' && (var[0] != '.' || var[1] != '\0') )
    resvar.AssignCat (var);
  else if (resfile.Length() == 0) resvar.AssignCat (def);
  else {
    Standard_Integer nomdeb, nomfin;
    nomdeb = resfile.SearchFromEnd ("/");
    if (nomdeb <= 0) nomdeb = resfile.SearchFromEnd("\\");  // pour NT
    if (nomdeb <  0) nomdeb = 0;
    nomfin = resfile.SearchFromEnd (".");
    if (nomfin < nomdeb) nomfin = resfile.Length() + 1;
    resvar = resfile.SubString(nomdeb+1,nomfin-1);
  }
  return iafic;
}
