0029915: Porting to VC 2017 : Regressions in Modeling Algorithms on VC 2017
[occt.git] / src / IFSelect / IFSelect_SessionFile.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14
15 #include <IFSelect_BasicDumper.hxx>
16 #include <IFSelect_Dispatch.hxx>
17 #include <IFSelect_GeneralModifier.hxx>
18 #include <IFSelect_IntParam.hxx>
19 #include <IFSelect_Modifier.hxx>
20 #include <IFSelect_SelectAnyList.hxx>
21 #include <IFSelect_SelectAnyType.hxx>
22 #include <IFSelect_SelectCombine.hxx>
23 #include <IFSelect_SelectControl.hxx>
24 #include <IFSelect_SelectDeduct.hxx>
25 #include <IFSelect_SelectExtract.hxx>
26 #include <IFSelect_Selection.hxx>
27 #include <IFSelect_SessionDumper.hxx>
28 #include <IFSelect_SessionFile.hxx>
29 #include <IFSelect_ShareOut.hxx>
30 #include <IFSelect_Transformer.hxx>
31 #include <IFSelect_WorkSession.hxx>
32 #include <Interface_Macros.hxx>
33 #include <Message.hxx>
34 #include <Message_Messenger.hxx>
35 #include <OSD_OpenFile.hxx>
36 #include <Standard_Transient.hxx>
37 #include <TCollection_AsciiString.hxx>
38 #include <TCollection_HAsciiString.hxx>
39 #include <TColStd_HSequenceOfInteger.hxx>
40
41 #include <stdio.h>
42 static int deja = 0;
43
44
45     IFSelect_SessionFile::IFSelect_SessionFile
46   (const Handle(IFSelect_WorkSession)& WS)
47 {
48   ClearLines();
49   themode = Standard_False;
50   if (!deja) {    // au moins celui-la :
51     Handle(IFSelect_BasicDumper) basedumper = new IFSelect_BasicDumper;
52     deja = 1;
53   }
54   thedone = Standard_False;
55   thelastgen = 0;
56   thesess = WS;
57 }
58
59     IFSelect_SessionFile::IFSelect_SessionFile
60   (const Handle(IFSelect_WorkSession)& WS, const Standard_CString filename)
61 {
62   ClearLines();
63   themode = Standard_True;
64   if (!deja) {    // au moins celui-la :
65     Handle(IFSelect_BasicDumper) basedumper = new IFSelect_BasicDumper;
66     deja = 1;
67   }
68   thedone = Standard_False;
69   theownflag = Standard_False;
70   thelastgen = 0;
71   thesess = WS;
72   thedone = (Write (filename) == 0);
73 //  Close fait par Write (selon les cas)
74 }
75
76
77     void  IFSelect_SessionFile::ClearLines ()
78       {  thelist.Clear();  thenl = 0;  }
79
80     Standard_Integer  IFSelect_SessionFile::NbLines () const
81       {  return thelist.Length();  }
82
83
84     const TCollection_AsciiString&  IFSelect_SessionFile::Line
85   (const Standard_Integer num) const
86       {  return thelist.Value(num);  }
87
88
89     void  IFSelect_SessionFile::AddLine (const Standard_CString line)
90       {  thelist.Append (TCollection_AsciiString(line) );  }
91
92     void  IFSelect_SessionFile::RemoveLastLine ()
93       {  if (thelist.Length() > 1) thelist.Remove(thelist.Length());  }
94
95
96     Standard_Boolean  IFSelect_SessionFile::WriteFile
97   (const Standard_CString filename)
98 {
99   FILE* lefic = OSD_OpenFile(filename,"w");
100   Standard_Integer nbl = thelist.Length();
101   for (Standard_Integer i = 1; i <= nbl; i ++)
102     fprintf (lefic,"%s\n",thelist.Value(i).ToCString());
103   fclose ( lefic );
104   ClearLines();
105   return Standard_True;
106 }
107
108     Standard_Boolean  IFSelect_SessionFile::ReadFile
109   (const Standard_CString filename)
110 {
111   char ligne[201];
112   FILE* lefic = OSD_OpenFile(filename,"r");
113   if (!lefic) return Standard_False;
114   ClearLines();
115 //  read mode : lire les lignes
116 //  On charge le fichier dans "thelist"
117   Standard_Boolean header = Standard_False;
118   for(;;) {
119     ligne[0] = '\0';
120     if (fgets(ligne,200,lefic) == NULL
121      || feof(lefic) != 0)
122     {
123       break;
124     }
125     if (ligne[0] == '\0') continue;
126 //  D abord ligne initiale ?
127     if (!header)
128       {  if (!RecognizeFile(ligne)) break;  header = Standard_True;  }
129     ligne[200] = '\0';  // fin forcee ...
130     TCollection_AsciiString onemore(ligne);
131     thelist.Append(onemore);
132   }
133   fclose ( lefic );
134   return header;
135 }
136
137     Standard_Boolean  IFSelect_SessionFile::RecognizeFile
138   (const Standard_CString headerline)
139 {
140   Handle(Message_Messenger) sout = Message::DefaultMessenger();
141
142   SplitLine (headerline);
143   if (theline.Length() != 4) { sout<<"File Form Incorrect"<<endl; return Standard_False; }
144   Handle(Standard_Type) sesstype = thesess->DynamicType();
145   if (!theline.Value(1).IsEqual("!XSTEP")  ||
146       !theline.Value(2).IsEqual("SESSION") ||
147       !theline.Value(4).IsEqual(sesstype->Name()) )
148     { sout<<"Lineno."<<thenl<<" : File Header Description Incorrect"<<endl; return Standard_False; }
149 //   Value(3) definit la VERSION du format de fichier
150   return Standard_True;
151 }
152
153
154     Standard_Integer  IFSelect_SessionFile::Write
155   (const Standard_CString filename)
156 {
157   thenewnum = 0;
158   Standard_Integer stat = WriteSession();
159   if (stat != 0) return stat;
160   stat = WriteEnd();
161   if (stat != 0) return stat;
162   return (WriteFile(filename) ? 0 : -1);
163 }
164
165     Standard_Integer  IFSelect_SessionFile::Read
166   (const Standard_CString filename)
167 {
168   if (!ReadFile(filename)) return -1;
169   thenewnum = 0;
170   Standard_Integer stat = ReadSession();
171   if (stat != 0) return stat;
172   stat = ReadEnd();
173   return stat;
174 }
175
176
177 //  ##################################################################
178 //  ########        WriteSession : Ecriture du contenu        ########
179
180     Standard_Integer  IFSelect_SessionFile::WriteSession ()
181 {
182   char laligne[200];
183   thedone = Standard_True;
184 //  ...  Preparation Specifique
185   thenames.Clear();
186   Standard_Integer nbidents = thesess->MaxIdent();
187   thenums = new TColStd_HArray1OfInteger (0,nbidents); thenums->Init(0);
188   Standard_Integer i; // svv Jan11 2000 : porting on DEC
189   for ( i = 1; i <= nbidents; i ++) {
190     Handle(Standard_Transient) item = thesess->Item(i);
191     if (!item.IsNull()) thenums->SetValue(i,-1);
192   }
193
194 //  ...  ECRITURE
195   sprintf (laligne,"!XSTEP SESSION V1 %s",thesess->DynamicType()->Name());
196   WriteLine(laligne,'\n');
197   sprintf (laligne,"!GENERALS");
198   WriteLine(laligne,'\n');
199   sprintf (laligne,"ErrorHandle %d", (thesess->ErrorHandle() ? 1 : 0));
200   WriteLine(laligne,'\n');
201   Handle(TColStd_HSequenceOfInteger) idents;
202   Standard_Integer nb;
203   Handle(TCollection_HAsciiString) name;
204
205   idents = thesess->ItemIdents(STANDARD_TYPE(IFSelect_IntParam));
206   nb = idents->Length();
207   if (nb > 0) WriteLine ("!INTEGERS",'\n');
208   Standard_Integer j; // svv Jan11 2000 : porting on DEC
209   for (j = 1; j <= nb; j ++) {
210     i = idents->Value(j);
211     Handle(IFSelect_IntParam) P = thesess->IntParam(i);
212     name = thesess->Name(P);
213     if (name.IsNull()) {
214       thenewnum ++;  idents->SetValue(i,thenewnum);
215       sprintf(laligne," #%d %d",thenewnum,P->Value());
216     }
217     else  sprintf(laligne," %s %d",name->ToCString(),P->Value());
218     WriteLine(laligne,'\n');
219   }
220
221   idents = thesess->ItemIdents(STANDARD_TYPE(TCollection_HAsciiString));
222   nb = idents->Length();
223   if (nb > 0) WriteLine ("!TEXTS",'\n');
224   for (j = 1; j <= nb; j ++) {
225     i = idents->Value(j);
226     Handle(TCollection_HAsciiString) P = thesess->TextParam(i);
227     name = thesess->Name(P);
228     if (name.IsNull()) {
229       thenewnum ++;  thenums->SetValue(i,thenewnum);
230       sprintf(laligne," #%d %s",thenewnum,P->ToCString());
231     }
232     else  sprintf(laligne," %s %s",name->ToCString(),P->ToCString());
233     WriteLine(laligne,'\n');
234   }
235
236   idents = thesess->ItemIdents(STANDARD_TYPE(IFSelect_Selection));
237   nb = idents->Length();
238   if (nb > 0) WriteLine ("!SELECTIONS",'\n');
239   for (j = 1; j <= nb; j ++) {
240     i = idents->Value(j);
241     Handle(IFSelect_Selection) P = thesess->Selection(i);
242     NewItem (i,P);
243 //  ..  Ecritures particulieres
244 //  ->  Traiter les principaux sous-types : Extract,AnyList,AnyType
245     DeclareAndCast(IFSelect_SelectExtract,sxt,P);
246     if (!sxt.IsNull()) {
247       sprintf(laligne," %c", (sxt->IsDirect() ? 'D' : 'R'));
248       WriteLine(laligne);
249     }
250     DeclareAndCast(IFSelect_SelectAnyList,sli,P);
251     if (!sli.IsNull()) {
252       SetOwn(Standard_False);
253       WriteLine(" LIST");
254       SendItem(sli->Lower());
255       SendItem(sli->Upper());
256       SetOwn(Standard_True);
257     }
258 //  ..  Ecritures specifiques selon dumpers
259     WriteOwn(P);
260     WriteLine("",'\n');
261   }
262
263   SetOwn(Standard_False);
264   if (nb > 0) WriteLine ("!SOURCES",'\n');
265   for (j = 1; j <= nb; j ++) {
266     i = idents->Value(j);
267     Handle(IFSelect_Selection) P = thesess->Selection(i);
268     Standard_Integer nbs = thesess->NbSources(P);
269     if (nbs == 0) continue;
270     name = thesess->Name(P);
271     if (name.IsNull())  sprintf(laligne," #%d %d",thenums->Value(i),nbs);
272     else                sprintf(laligne," %s %d",name->ToCString(),nbs);
273     WriteLine(laligne);
274     for (Standard_Integer k = 1; k <= nbs; k ++)
275       SendItem (thesess->Source(P,k));
276     WriteLine("",'\n');
277   }
278
279   idents = thesess->ItemIdents(STANDARD_TYPE(IFSelect_GeneralModifier));
280   nb = idents->Length();
281   if (nb > 0) WriteLine ("!MODIFIERS",'\n');
282   for (j = 1; j <= nb; j ++) {
283 //  Description de base des Modifiers, donc sans Selection ni Dispatch-Rank
284     i = idents->Value(j);
285     Handle(IFSelect_GeneralModifier) P = thesess->GeneralModifier(i);
286     NewItem (i,P);
287     SetOwn(Standard_True);
288 //  ..  Ecritures specifiques selon dumpers
289     WriteOwn(P);
290     WriteLine("",'\n');
291   }
292
293   idents = thesess->ItemIdents(STANDARD_TYPE(IFSelect_Transformer));
294   nb = idents->Length();
295   if (nb > 0) WriteLine ("!TRANSFORMERS",'\n');
296   for (j = 1; j <= nb; j ++) {
297 //  Description des Transformers
298     i = idents->Value(j);
299     Handle(IFSelect_Transformer) P = thesess->Transformer(i);
300     NewItem (i,P);
301     SetOwn(Standard_True);
302 //  ..  Ecritures specifiques selon dumpers
303     WriteOwn(P);
304     WriteLine("",'\n');
305   }
306
307   SetOwn(Standard_False);
308   idents = thesess->ItemIdents(STANDARD_TYPE(IFSelect_Dispatch));
309   nb = idents->Length();
310   if (nb > 0) WriteLine ("!DISPATCHES",'\n');
311   for (j = 1; j <= nb; j ++) {
312     i = idents->Value(j);
313     Handle(IFSelect_Dispatch) P = thesess->Dispatch(i);
314     NewItem (i,P);
315 //  ..  Final Selection
316     SetOwn(Standard_False);
317     SendItem(P->FinalSelection());
318     SetOwn(Standard_True);
319 //  ..  Ecritures specifiques selon dumpers
320     WriteOwn(P);
321     WriteLine("",'\n');
322   }
323
324   WriteLine ("!FILENAMING");
325   SetOwn(Standard_False);
326   Handle(TCollection_HAsciiString) namingpart = thesess->FilePrefix();
327   if (namingpart->IsEmpty()) namingpart.Nullify();
328   if (namingpart.IsNull()) SendVoid();
329   else SendText(namingpart->ToCString());
330   namingpart = thesess->DefaultFileRoot();
331   if (namingpart->IsEmpty()) namingpart.Nullify();
332   if (namingpart.IsNull()) SendVoid();
333   else SendText(namingpart->ToCString());
334   namingpart = thesess->FileExtension();
335   if (namingpart->IsEmpty()) namingpart.Nullify();
336   if (namingpart.IsNull()) SendVoid();
337   else SendText(namingpart->ToCString());
338   WriteLine("",'\n');
339
340   for (j = 1; j <= nb; j ++) {
341     i = idents->Value(j);
342     Handle(IFSelect_Dispatch) P = thesess->Dispatch(i);
343     if (!P->HasRootName()) continue;
344     namingpart = P->RootName();
345     SetOwn(Standard_False);
346     SendItem(P);
347     sprintf(laligne," %s",namingpart->ToCString());
348     WriteLine(laligne,' ');
349     WriteLine("",'\n');
350   }
351
352 //   Pour les Modifiers, ATTENTION car il faut respecter l ORDRE effectif
353 //   Or il y a deux listes : Model Modifiers; File Modifiers
354 //   Les Modifiers eux-memes ont deja ete ecrits
355 //   Ici, on ecrit simplement leur utilisation dans l envoi final
356   for (Standard_Integer formod = 1; formod >= 0; formod --) {
357     idents = thesess->FinalModifierIdents((formod > 0));  // donnes dans l ordre d application
358     nb = idents->Length();
359     if (nb == 0) continue;
360     if (formod > 0) WriteLine ("!MODELMODIFIERS",'\n');
361     else            WriteLine ("!FILEMODIFIERS",'\n');
362     for (j = 1; j <= nb; j ++) {
363       i = idents->Value(j);
364       Handle(IFSelect_GeneralModifier) P = thesess->GeneralModifier(i);
365       SetOwn(Standard_False);
366       SendItem(P);
367       //  ..  Parametres Generaux (les specifiques ont deja ete envoyes)
368       SendItem(P->Selection());
369       SendItem(P->Dispatch());
370       WriteLine("",'\n');
371     }
372   }
373
374 //  ...  Conclusion
375   theline.Clear();
376   return 0;
377 }
378
379     Standard_Integer  IFSelect_SessionFile::WriteEnd ()
380 {
381   WriteLine("!XSTEP END",'\n');   // sinon, cf sous-types de SessionFile ...
382   return 0;
383 }
384
385
386     void  IFSelect_SessionFile::WriteLine
387   (const Standard_CString line, const Standard_Character follow)
388 {
389   if (line[0] != '\0') thebuff.AssignCat (line);
390   if (follow == '\0') return;
391   if (follow != '\n') thebuff.AssignCat(follow);
392   else {
393     thelist.Append(thebuff);
394     thebuff.Clear();
395     thenl ++;
396   }
397 }
398
399     Standard_Boolean  IFSelect_SessionFile::WriteOwn
400   (const Handle(Standard_Transient)& item)
401 {
402   if (item.IsNull()) return Standard_False;
403   SetOwn(Standard_True);
404   Handle(IFSelect_SessionDumper) dumper = IFSelect_SessionDumper::First();
405   while (!dumper.IsNull()) {
406     if (dumper->WriteOwn(*this,item)) break;
407     dumper = dumper->Next();
408   }
409   SetOwn(Standard_False);
410   return (!dumper.IsNull());    // IsNull -> echec
411 }
412
413
414
415 //  ##################################################################
416 //  ########        ReadSession  :  Lecture du contenu        ########
417
418     Standard_Integer  IFSelect_SessionFile::ReadSession ()
419 {
420   Handle(Message_Messenger) sout = Message::DefaultMessenger();
421
422   thedone = Standard_True;
423 //  ...  Preparation Specifique
424   thenums.Nullify();
425   thenames.Clear();
426 //  ..  Donnees generales, controle
427   if (!ReadLine()) return 1;
428   if (theline.Length() != 4) { sout<<"File Form Incorrect"<<endl; return 1; }
429   Handle(Standard_Type) sesstype = thesess->DynamicType();
430   if (!theline.Value(1).IsEqual("!XSTEP")  ||
431       !theline.Value(2).IsEqual("SESSION") ||
432       !theline.Value(4).IsEqual(sesstype->Name()) )
433     { sout<<"Lineno."<<thenl<<" : File Header Description Incorrect"<<endl; return 1; }
434 //   Value(3) definit la VERSION du format de fichier
435   if (!ReadLine()) return 1;
436
437 //  ..  Parametres Generaux
438   Standard_Integer rubr =
439     (theline.Length() == 1 && theline.Value(1).IsEqual("!GENERALS"));
440   while (rubr) {
441     if (!ReadLine()) return 1;
442     if (theline.Length() == 0) continue;
443     const TCollection_AsciiString& ungen = theline.Value(1);
444     if (ungen.Value(1) == '!') break;  // fin des generaux
445     if (ungen.IsEqual("ErrorHandle")) {
446       if (theline.Length() != 2)
447         { sout<<"Lineno."<<thenl<<" : ErrorHandle Description Incorrect"<<endl; continue; }
448       if      (theline.Value(2).IsEqual("0"))
449         thesess->SetErrorHandle(Standard_False);
450       else if (theline.Value(2).IsEqual("1"))
451         thesess->SetErrorHandle(Standard_True);
452       else { sout<<"Lineno."<<thenl<<" : ErrorHandle Incorrect : "<<theline.Value(2)<<endl; continue; }
453       continue;
454     }
455     else sout<<"Lineno."<<thenl<<" : Unknown General Parameter : "<<ungen<<" , ignored"<<endl;
456   }
457
458 //  ..  IntParams
459 //   deja fait  if (!ReadLine()) return 1;
460   rubr = (theline.Length() == 1 && theline.Value(1).IsEqual("!INTEGERS"));
461   while (rubr) {
462     if (!ReadLine()) return 1;
463     if (theline.Value(1).Value(1) == '!') break;    // liste suivante
464     if (theline.Length() != 2)
465       { sout<<"Lineno."<<thenl<<" : An Integer Parameter is badly defined"<<endl; continue; }
466     Handle(IFSelect_IntParam) par = new IFSelect_IntParam;
467     par->SetValue ( atoi(theline.Value(2).ToCString()) );
468     AddItem (par);
469   }
470
471 //  .. TextParams (ligne de garde deja lue)
472   rubr = (theline.Length() == 1 && theline.Value(1).IsEqual("!TEXTS"));
473   while (rubr) {
474     if (!ReadLine()) return 1;
475     if (theline.Value(1).Value(1) == '!') break;    // liste suivante
476     if (theline.Length() != 2)
477       { sout<<"Lineno."<<thenl<<" : A Text Parameter is badly defined"<<endl; continue; }
478 //    Attention, un texte peut contenir des blancs ...  repartir de line(thenl)
479     TCollection_AsciiString oneline = thelist.Value(thenl);
480     Standard_Integer iw = 0, inc = 0;
481     for (Standard_Integer ic = 1; ic <= oneline.Length(); ic ++) {
482       char unc = oneline.Value(1);
483       inc = ic;
484       if (unc == ' ') iw = 1;
485       else if (iw > 0) break;
486     }
487     oneline.Remove (1,inc);
488     AddItem ( new TCollection_HAsciiString (oneline.ToCString()) );
489   }
490
491 //  .. Selections (ligne de garde deja lue)
492   rubr = (theline.Length() == 1 && theline.Value(1).IsEqual("!SELECTIONS"));
493   while (rubr) {
494     if (!ReadLine()) return 1;
495     if (theline.Value(1).Value(1) == '!') break;    // liste suivante
496     if (theline.Length() < 2)
497       { sout<<"Lineno."<<thenl<<" : A Selection is badly defined"<<endl; continue; }
498 //  ..  Analyse de certains cas generaux
499     Handle(IFSelect_IntParam) low,up;
500     Standard_Integer firstown = 3;
501     Standard_Integer direct   = 0;
502     Standard_Integer numlist  = 0;
503     if (theline.Length() > 2) {
504       if      (theline.Value(3).IsEqual("D")) direct = 1;
505       else if (theline.Value(3).IsEqual("R")) direct = -1;
506       if (direct != 0) firstown ++;
507       if (firstown+2 <= theline.Length()) {
508         if (theline.Value(firstown).IsEqual("LIST"))  {
509           numlist = firstown;  firstown += 3;
510           low = GetCasted(IFSelect_IntParam,ItemValue(numlist+1));
511           up  = GetCasted(IFSelect_IntParam,ItemValue(numlist+2));
512         }
513       }
514       SetLastGeneral (firstown-1);
515     }
516     Handle(Standard_Transient) item;   // a fournir ...
517     ReadOwn(item);
518     if (item.IsNull()) continue;
519     DeclareAndCast(IFSelect_SelectExtract,sxt,item);
520     if (!sxt.IsNull()) {
521       if (direct == 0) sout<<"Lineno."<<thenl<<" : A SelectExtract is badly defined"<<endl;
522       else  sxt->SetDirect( (direct > 0) );
523     }
524     DeclareAndCast(IFSelect_SelectAnyList,sli,item);
525     if (!sli.IsNull()) {
526       if (numlist == 0) sout<<"Lineno."<<thenl<<" : A SelectAnyList is badly defined"<<endl;
527       else sli->SetRange(low,up);
528     }
529     AddItem(item);
530   }
531
532 //  .. Sources
533   rubr = (theline.Length() == 1 && theline.Value(1).IsEqual("!SOURCES"));
534   while (rubr) {
535     if (!ReadLine()) return 1;
536     if (theline.Value(1).Value(1) == '!') break;    // liste suivante
537     if (theline.Length() < 3)
538       { sout<<"Lineno."<<thenl<<" : A Selection Source List is badly defined"<<endl; continue; }
539     DeclareAndCast(IFSelect_Selection,sel,ItemValue(1));
540     if (sel.IsNull())
541       { sout<<"Lineno."<<thenl<<" : A Source List is not for a Selection"<<endl; continue; }
542     Standard_Integer nbs = atoi(theline.Value(2).ToCString());
543 //  .. Differents cas reconnus
544     DeclareAndCast(IFSelect_SelectExtract,sxt,sel);
545     if (!sxt.IsNull()) {
546       if (nbs > 1)
547         sout<<"Lineno."<<thenl<<" : SelectExtract, more than one source, followings ignored"<<endl;
548       DeclareAndCast(IFSelect_Selection,source,ItemValue(3));
549       sxt->SetInput(source);
550     }
551     DeclareAndCast(IFSelect_SelectDeduct,sdt,sel);
552     if (!sdt.IsNull()) {
553       if (nbs > 1)
554         sout<<"Lineno."<<thenl<<" : SelectDeduct, more than one source, followings ignored"<<endl;
555       sdt->SetInput(GetCasted(IFSelect_Selection,ItemValue(3)));
556     }
557     DeclareAndCast(IFSelect_SelectControl,sct,sel);
558     if (!sct.IsNull()) {
559       if (nbs != 2)
560         sout<<"Lineno."<<thenl<<" : SelectControl, not two sources, followings ignored"<<endl;
561       sct->SetMainInput   (GetCasted(IFSelect_Selection,ItemValue(3)));
562       sct->SetSecondInput (GetCasted(IFSelect_Selection,ItemValue(4)));
563     }
564     DeclareAndCast(IFSelect_SelectCombine,sco,sel);
565     if (!sco.IsNull()) {
566       for (Standard_Integer j = 1; j <= nbs; j ++)
567         sco->Add(GetCasted(IFSelect_Selection,ItemValue(j+2)));
568     }
569   }
570
571 //  ... Modifiers en tout genre
572   rubr = (theline.Length() == 1 && theline.Value(1).IsEqual("!MODIFIERS"));
573   while (rubr) {
574     if (!ReadLine()) return 1;
575     if (theline.Value(1).Value(1) == '!') break;    // liste suivante
576     if (theline.Length() < 2)
577       { sout<<"Lineno."<<thenl<<" : A Modifier is badly defined"<<endl; continue; }
578     Handle(Standard_Transient) item;   // a fournir ...
579     ReadOwn(item);
580     if (item.IsNull()) continue;
581     DeclareAndCast(IFSelect_GeneralModifier,modif,item);
582     if (modif.IsNull())
583       { sout<<"Lineno."<<thenl<<" : A Modifier has not been Recognized"<<endl; continue; }
584     AddItem(modif,Standard_False);  // active plus tard
585   }
586
587 //  ... Transformers
588   rubr = (theline.Length() == 1 && theline.Value(1).IsEqual("!TRANSFORMERS"));
589   while (rubr) {
590     if (!ReadLine()) return 1;
591     if (theline.Value(1).Value(1) == '!') break;    // liste suivante
592     if (theline.Length() < 2)
593       { sout<<"Lineno."<<thenl<<" : A Transformer is badly defined"<<endl; continue; }
594     Handle(Standard_Transient) item;   // a fournir ...
595     ReadOwn(item);
596     if (item.IsNull()) continue;
597     DeclareAndCast(IFSelect_Transformer,trf,item);
598     if (trf.IsNull())
599       { sout<<"Lineno."<<thenl<<" : A Transformer has not been Recognized"<<endl; continue; }
600     AddItem(trf,Standard_False);  // active plus tard
601   }
602
603 //  ... Dispatches (ligne de garde deja lue)
604   rubr = (theline.Length() == 1 && theline.Value(1).IsEqual("!DISPATCHES"));
605   while (rubr) {
606     if (!ReadLine()) return 1;
607     if (theline.Value(1).Value(1) == '!') break;    // liste suivante
608     if (theline.Length() < 3)
609       { sout<<"Lineno."<<thenl<<" : A Dispatch is badly defined"<<endl; continue; }
610     DeclareAndCast(IFSelect_Selection,input,ItemValue(3));
611     SetLastGeneral(3);
612     Handle(Standard_Transient) item;   // a fournir ...
613     ReadOwn(item);
614     if (item.IsNull()) continue;
615     DeclareAndCast(IFSelect_Dispatch,disp,item);
616     if (disp.IsNull())
617       { sout<<"Lineno."<<thenl<<" : A Dispatch has not been Recognized"<<endl; continue; }
618     AddItem(disp);
619     thesess->SetItemSelection(disp,input);
620   }
621
622 //  ... FileNaming (ligne de garde deja lue)
623 //  ..  Modifiers deja lus et charges
624   rubr = (theline.Length() == 4 && theline.Value(1).IsEqual("!FILENAMING"));
625   if (rubr) {
626     if (!IsVoid(2)) thesess->SetFilePrefix      (TextValue(2).ToCString());
627     if (!IsVoid(3)) thesess->SetDefaultFileRoot (TextValue(3).ToCString());
628     if (!IsVoid(4)) thesess->SetFileExtension   (TextValue(4).ToCString());
629   }
630   while (rubr) {
631     if (!ReadLine()) return 1;
632     if (theline.Value(1).Value(1) == '!') break;    // liste suivante
633     if (theline.Length() != 2)
634       { sout<<"Lineno."<<thenl<<" : A File Root is badly defined"<<endl; continue; }
635     DeclareAndCast(IFSelect_Dispatch,disp,ItemValue(1));
636     thesess->SetFileRoot (disp,theline.Value(2).ToCString());
637   }
638
639 //  ... Modifiers (ligne de garde deja lue)
640 //  ... Attention, deux listes (MODELMODIFIERS et FILEMODIFIERS)
641   for (Standard_Integer formod = 1; formod >= 0; formod --) {
642     rubr = (theline.Length() == 1 &&
643             ( (formod == 1 && theline.Value(1).IsEqual("!MODELMODIFIERS")) ||
644               (formod == 0 && theline.Value(1).IsEqual("!FILEMODIFIERS"))  ) );
645 //    if ( formod == 1 && ( theline.Length() != 1 ||
646 //                       !theline.Value(1).IsEqual("!MODELMODIFIERS")) )
647 //      { sout<<"Lineno."<<thenl<<" : Model Modifier List Incorrect"<<endl;  return 1; }
648 //    if ( formod == 0 && ( theline.Length() != 1 ||
649 //                       !theline.Value(1).IsEqual("!FILEMODIFIERS")) )
650 //      { sout<<"Lineno."<<thenl<<" : File Modifier List Incorrect"<<endl;  return 1; }
651     while (rubr) {
652       if (!ReadLine()) return 1;
653       if (theline.Value(1).Value(1) == '!') break;    // liste suivante
654       if (theline.Length() < 3)
655         { sout<<"Lineno."<<thenl<<" : A General Modifier is badly defined"<<endl; continue; }
656       DeclareAndCast(IFSelect_GeneralModifier,modif,ItemValue(1));
657       DeclareAndCast(IFSelect_Selection,input,ItemValue(2));
658       DeclareAndCast(IFSelect_Dispatch,disp,ItemValue(3));
659       if (modif.IsNull())
660         { sout<<"Lineno."<<thenl<<" : A General Modifier has not been Recognized"<<endl; continue; }
661       thesess->SetItemSelection   (modif,input);
662       if (!disp.IsNull()) thesess->SetAppliedModifier (modif,disp);
663       else                thesess->SetAppliedModifier (modif,thesess->ShareOut());
664     }
665   }
666
667 //  ...  Conclusion : voir ReadEnd (separe)
668   return 0;
669 }
670
671     Standard_Integer  IFSelect_SessionFile::ReadEnd ()
672 {
673   Handle(Message_Messenger) sout = Message::DefaultMessenger();
674   if ( theline.Length() != 2 ||
675       !theline.Value(1).IsEqual("!XSTEP") ||
676       !theline.Value(2).IsEqual("END"))
677     { sout<<"End of File Incorrect, lineno"<<thenl<<endl;  return 1; }
678   return 0;
679 }
680
681
682     Standard_Boolean  IFSelect_SessionFile::ReadLine ()
683 {
684   if (thenl >= thelist.Length()) return Standard_False;
685   thenl ++;
686   Standard_CString ligne = thelist.Value(thenl).ToCString();
687 //   Lignes vides ?
688   if (ligne[0] == '\0') return ReadLine();
689   SplitLine (ligne);
690   return Standard_True;
691 }
692
693
694     void  IFSelect_SessionFile::SplitLine (const Standard_CString line)
695 {
696   char mot[80];
697   theline.Clear();
698   Standard_Integer nbc  = 0;
699   Standard_Boolean word = (line[0] > ' ');
700   for (Standard_Integer i = 0; line[i] != '\0'; i ++) {
701     if (line[i] > ' ') {
702       if (!word) {  nbc = 0; word = Standard_True;  }
703       mot[nbc] = line[i];  nbc ++;
704     } else {
705       if (word) {
706         word = Standard_False;
707         mot[nbc] = '\0';
708         theline.Append (TCollection_AsciiString(mot));
709       }
710       if (line[i] == '\0' || line[i] == '\n') break;
711     }
712   }
713   thelastgen = 0;
714 }
715
716     Standard_Boolean  IFSelect_SessionFile::ReadOwn
717   (Handle(Standard_Transient)& item)
718 {
719   Handle(Message_Messenger) sout = Message::DefaultMessenger();
720
721   if (theline.Length() < 2) return Standard_False;
722   const TCollection_AsciiString& type = theline.Value(2);
723   if (thelastgen < 2) thelastgen = 2;        // mini : ident+type d abord
724 //  thelastgen = theline.Length();
725 //  for (Standard_Integer i = theline.Length(); i > 0; i --) {
726 //    if (theline.Value(i).Value(1) == ':') thelastgen = i - 1;
727 //  }
728   Handle(IFSelect_SessionDumper) dumper = IFSelect_SessionDumper::First();
729   while (!dumper.IsNull()) {
730     if (dumper->ReadOwn(*this,type,item)) break;
731     dumper = dumper->Next();
732   }
733   if (dumper.IsNull()) sout<<" -- Lineno."<<thenl<<" : an Item could not be read"<<endl;
734   return (!dumper.IsNull());    // IsNull -> echec
735 }
736
737
738     void  IFSelect_SessionFile::AddItem
739   (const Handle(Standard_Transient)& item, const Standard_Boolean active)
740 {
741   Handle(Message_Messenger) sout = Message::DefaultMessenger();
742
743   const TCollection_AsciiString& name = theline.Value(1);
744   Standard_Integer id = 0;
745   if (!item.IsNull()) {
746     if (name.Value(1) == '#') id = thesess->AddItem(item,active);
747     else if (!thesess->NamedItem(name.ToCString()).IsNull()) id =
748       thesess->AddItem(item,active);
749     else id = thesess->AddNamedItem(name.ToCString(),item,active);
750   }
751   else sout<<"Lineno."<<thenl<<" -- Name : "<<name
752     <<" : Item could not be defined" << endl;
753   thenames.Bind(name,id);
754 }
755
756     Standard_Boolean  IFSelect_SessionFile::IsDone () const
757       {  return thedone;  }
758
759     Handle(IFSelect_WorkSession)  IFSelect_SessionFile::WorkSession () const
760       {  return thesess;  }
761
762 //  ########                Actions Unitaires d ECRITURE               ########
763
764     void  IFSelect_SessionFile::NewItem
765   (const Standard_Integer ident, const Handle(Standard_Transient)& par)
766 {
767   char laligne[100];
768   if (!thesess->HasName(par)) {
769     thenewnum ++;  thenums->SetValue(ident,thenewnum);
770     sprintf(laligne," #%d %s",thenewnum,par->DynamicType()->Name());
771   }
772   else  sprintf(laligne," %s %s",thesess->Name(par)->ToCString(),
773                 par->DynamicType()->Name());
774   WriteLine(laligne);
775 }
776
777     void  IFSelect_SessionFile::SetOwn (const Standard_Boolean mode)
778       {  theownflag = mode;  }
779
780     void  IFSelect_SessionFile::SendVoid ()
781 {
782 ////  if (theownflag) WriteLine(" :$");
783   WriteLine(" $");
784 }
785
786     void  IFSelect_SessionFile::SendItem (const Handle(Standard_Transient)& par)
787 {
788   Handle(Message_Messenger) sout = Message::DefaultMessenger();
789
790   char laligne[100];
791   Standard_Integer filenum = 0;
792   Standard_Integer id = thesess->ItemIdent(par);
793   if (id != 0) filenum = thenums->Value(id);
794   if (filenum == 0) {
795     if (!par.IsNull()) sout << "Lineno " << thenl << " --  Unknown Item : "
796        << " Type:" << par->DynamicType()->Name() << endl;  //sout<<Handle par
797     SendVoid();
798     thedone = Standard_False;
799     return;
800   }
801 ////  if (theownflag) WriteLine(" :");
802 ////  else            WriteLine(" ");
803   if (filenum < 0) sprintf(laligne," :%s",thesess->Name(par)->ToCString());
804   else sprintf(laligne," #%d",filenum);
805   WriteLine(laligne);
806 }
807
808     void  IFSelect_SessionFile::SendText (const Standard_CString text)
809 {
810   char laligne[100];
811 ////  if (theownflag) sprintf(laligne," :%s",text);
812   sprintf(laligne," %s",text);
813   WriteLine(laligne);
814 }
815
816
817 //  ########                Actions Unitaires de LECTURE               ########
818
819     void  IFSelect_SessionFile::SetLastGeneral (const Standard_Integer lastgen)
820       {  thelastgen = lastgen;  }
821
822     Standard_Integer  IFSelect_SessionFile::NbParams () const
823       {  return theline.Length() - thelastgen;  }
824
825
826     Standard_Boolean  IFSelect_SessionFile::IsVoid
827   (const Standard_Integer num) const
828 {
829   Standard_Integer nm = num + thelastgen;
830   if (nm <= 0 || nm > theline.Length()) return Standard_True;
831   const TCollection_AsciiString& term = theline.Value(nm);
832   return (term.IsEqual ("$") || term.IsEqual (":$") );
833 }
834
835     Standard_Boolean  IFSelect_SessionFile::IsText
836   (const Standard_Integer num) const
837 {
838   Standard_Integer nm = num + thelastgen;
839   if (nm <= 0 || nm > theline.Length()) return Standard_False;
840   const TCollection_AsciiString& term = theline.Value(nm);
841   if (term.Value(1) == ':') return Standard_False;
842   if (term.Value(1) == '#') return Standard_False;
843   if (term.IsEqual("$"))    return Standard_False;
844   return Standard_True;
845 }
846
847     const TCollection_AsciiString&  IFSelect_SessionFile::ParamValue
848   (const Standard_Integer num) const
849       {  return theline.Value(num+thelastgen);  }
850
851
852     TCollection_AsciiString  IFSelect_SessionFile::TextValue
853   (const Standard_Integer num) const
854 {
855   Standard_Integer nm = num + thelastgen;
856   TCollection_AsciiString res;
857   if (nm <= 0 || nm > theline.Length()) return res;
858   res = theline.Value(nm);
859   if (res.Value( res.Length() ) == '"') res.Remove(res.Length());
860   if (res.Value(1) == ':') res.Remove(1);
861   if (res.Value(1) == '"') res.Remove(1);
862   return res;
863 }
864
865     Handle(Standard_Transient)  IFSelect_SessionFile::ItemValue
866   (const Standard_Integer num) const
867 {
868   Handle(Message_Messenger) sout = Message::DefaultMessenger();
869
870   Handle(Standard_Transient) res;
871   Standard_Integer nm = num + thelastgen;
872   if (nm <= 0 || nm > theline.Length()) return res;
873   Standard_Integer id;
874   TCollection_AsciiString name = theline.Value(nm);
875   if (name.Value(1) == ':') name.Remove(1);
876   if (name.IsEqual("$")) return res;    // item non-defini justement
877   if (!thenames.Find(name, id)) {
878     sout << " -- Item Unknown in File : " << name
879       << " lineno " << thenl << " param." << nm << endl;
880     id = 0;
881   }
882   return thesess->Item(id);
883 }
884
885
886     void  IFSelect_SessionFile::Destroy ()
887 {   }  // agit si File non ferme, sinon ne fait rien